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',
84 'civicrm_activity_contact',
87 'civicrm_group_contact',
88 'civicrm_saved_search',
89 'civicrm_group_contact_cache',
92 $this->quickCleanup($tablesToTruncate, TRUE);
97 * Test civicrm_contact_create.
99 * Verify that attempt to create individual contact with only
100 * first and last names succeeds
102 public function testAddCreateIndividual() {
103 $oldCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
105 'first_name' => 'abc1',
106 'contact_type' => 'Individual',
107 'last_name' => 'xyz1',
110 $contact = $this->callAPISuccess('contact', 'create', $params);
111 $this->assertTrue(is_numeric($contact['id']));
112 $this->assertTrue($contact['id'] > 0);
113 $newCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
114 $this->assertEquals($oldCount +
1, $newCount);
116 $this->assertDBState('CRM_Contact_DAO_Contact',
123 * Test that it is possible to prevent cache clearing via option.
125 * Cache clearing is bypassed if 'options' => array('do_not_reset_cache' => 1 is used.
127 public function testCreateIndividualNoCacheClear() {
129 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
130 $groupID = $this->groupCreate();
132 $this->putGroupContactCacheInClearableState($groupID, $contact);
134 $this->callAPISuccess('contact', 'create', array('id' => $contact['id']));
135 $this->assertEquals(0, CRM_Core_DAO
::singleValueQuery("SELECT count(*) FROM civicrm_group_contact_cache"));
137 // Rinse & repeat, but with the option.
138 $this->putGroupContactCacheInClearableState($groupID, $contact);
139 CRM_Core_Config
::setPermitCacheFlushMode(FALSE);
140 $this->callAPISuccess('contact', 'create', array('id' => $contact['id']));
141 $this->assertEquals(1, CRM_Core_DAO
::singleValueQuery("SELECT count(*) FROM civicrm_group_contact_cache"));
142 CRM_Core_Config
::setPermitCacheFlushMode(TRUE);
146 * Test for international string acceptance (CRM-10210).
147 * Requires the databsase to be in utf8.
149 * @dataProvider getInternationalStrings
151 * @param string $string
152 * String to be tested.
153 * @param bool $checkCharSet
154 * Bool to see if we should check charset.
158 public function testInternationalStrings($string, $checkCharSet = FALSE) {
159 $this->callAPISuccess('Contact', 'create', array_merge(
161 array('first_name' => $string)
164 if (!CRM_Utils_SQL
::supportStorageOfAccents()) {
165 $this->markTestIncomplete('Database is not Charset UTF8 therefore can not store accented strings properly');
168 $result = $this->callAPISuccessGetSingle('Contact', array('first_name' => $string));
169 $this->assertEquals($string, $result['first_name']);
171 $organizationParams = array(
172 'organization_name' => $string,
173 'contact_type' => 'Organization',
176 $this->callAPISuccess('Contact', 'create', $organizationParams);
177 $result = $this->callAPISuccessGetSingle('Contact', $organizationParams);
178 $this->assertEquals($string, $result['organization_name']);
182 * Get international string data for testing against api calls.
184 public function getInternationalStrings() {
185 $invocations = array();
186 $invocations[] = array('Scarabée', TRUE);
187 $invocations[] = array('Iñtërnâtiônàlizætiøn', TRUE);
188 $invocations[] = array('これは日本語のテキストです。読めますか');
189 $invocations[] = array('देखें हिन्दी कैसी नजर आती है। अरे वाह ये तो नजर आती है।');
194 * Test civicrm_contact_create.
196 * Verify that preferred language can be set.
198 public function testAddCreateIndividualWithPreferredLanguage() {
200 'first_name' => 'abc1',
201 'contact_type' => 'Individual',
202 'last_name' => 'xyz1',
203 'preferred_language' => 'es_ES',
206 $contact = $this->callAPISuccess('contact', 'create', $params);
207 $this->getAndCheck($params, $contact['id'], 'Contact');
211 * Test civicrm_contact_create with sub-types.
213 * Verify that sub-types are created successfully and not deleted by subsequent updates.
215 public function testIndividualSubType() {
217 'first_name' => 'test abc',
218 'contact_type' => 'Individual',
219 'last_name' => 'test xyz',
220 'contact_sub_type' => array('Student', 'Staff'),
222 $contact = $this->callAPISuccess('contact', 'create', $params);
223 $cid = $contact['id'];
227 'middle_name' => 'foo',
229 $this->callAPISuccess('contact', 'create', $params);
230 unset($params['middle_name']);
232 $contact = $this->callAPISuccess('contact', 'get', $params);
234 $this->assertEquals(array('Student', 'Staff'), $contact['values'][$cid]['contact_sub_type']);
238 * Verify that we can retreive contacts of different sub types
240 public function testGetMultipleContactSubTypes() {
242 // This test presumes that there are no parents or students in the dataset
245 $student = $this->callAPISuccess('contact', 'create', array(
246 'email' => 'student@example.com',
247 'contact_type' => 'Individual',
248 'contact_sub_type' => 'Student',
252 $parent = $this->callAPISuccess('contact', 'create', array(
253 'email' => 'parent@example.com',
254 'contact_type' => 'Individual',
255 'contact_sub_type' => 'Parent',
259 $this->callAPISuccess('contact', 'create', array(
260 'email' => 'parent@example.com',
261 'contact_type' => 'Individual',
264 // get all students and parents
265 $getParams = array('contact_sub_type' => array('IN' => array('Parent', 'Student')));
266 $result = civicrm_api3('contact', 'get', $getParams);
268 // check that we retrieved the student and the parent
269 $this->assertArrayHasKey($student['id'], $result['values']);
270 $this->assertArrayHasKey($parent['id'], $result['values']);
271 $this->assertEquals(2, $result['count']);
276 * Verify that attempt to create contact with empty params fails.
278 public function testCreateEmptyContact() {
279 $this->callAPIFailure('contact', 'create', array());
283 * Verify that attempt to create contact with bad contact type fails.
285 public function testCreateBadTypeContact() {
287 'email' => 'man1@yahoo.com',
288 'contact_type' => 'Does not Exist',
290 $this->callAPIFailure('contact', 'create', $params, "'Does not Exist' is not a valid option for field contact_type");
294 * Verify that attempt to create individual contact without required fields fails.
296 public function testCreateBadRequiredFieldsIndividual() {
298 'middle_name' => 'This field is not required',
299 'contact_type' => 'Individual',
301 $this->callAPIFailure('contact', 'create', $params);
305 * Verify that attempt to create household contact without required fields fails.
307 public function testCreateBadRequiredFieldsHousehold() {
309 'middle_name' => 'This field is not required',
310 'contact_type' => 'Household',
312 $this->callAPIFailure('contact', 'create', $params);
316 * Test required field check.
318 * Verify that attempt to create organization contact without required fields fails.
320 public function testCreateBadRequiredFieldsOrganization() {
322 'middle_name' => 'This field is not required',
323 'contact_type' => 'Organization',
326 $this->callAPIFailure('contact', 'create', $params);
330 * Verify that attempt to create individual contact with only an email succeeds.
332 public function testCreateEmailIndividual() {
333 $primaryEmail = 'man3@yahoo.com';
334 $notPrimaryEmail = 'man4@yahoo.com';
336 'email' => $primaryEmail,
337 'contact_type' => 'Individual',
338 'location_type_id' => 1,
341 $contact1 = $this->callAPISuccess('contact', 'create', $params);
343 $this->assertEquals(3, $contact1['id']);
344 $email1 = $this->callAPISuccess('email', 'get', array('contact_id' => $contact1['id']));
345 $this->assertEquals(1, $email1['count']);
346 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
348 $email2 = $this->callAPISuccess('email', 'create', array('contact_id' => $contact1['id'], 'is_primary' => 0, 'email' => $notPrimaryEmail));
350 // Case 1: Check with criteria primary 'email' => array('IS NOT NULL' => 1)
351 $result = $this->callAPISuccess('contact', 'get', array('email' => array('IS NOT NULL' => 1)));
352 $primaryEmailContactIds = array_keys($result['values']);
353 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
355 // Case 2: Check with criteria primary 'email' => array('<>' => '')
356 $result = $this->callAPISuccess('contact', 'get', array('email' => array('<>' => '')));
357 $primaryEmailContactIds = array_keys($result['values']);
358 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
360 // Case 3: Check with email_id='primary email id'
361 $result = $this->callAPISuccess('contact', 'get', array('email_id' => $email1['id']));
362 $this->assertEquals(1, $result['count']);
363 $this->assertEquals($contact1['id'], $result['id']);
365 $this->callAPISuccess('contact', 'delete', $contact1);
369 * Test creating individual by name.
371 * Verify create individual contact with only first and last names succeeds.
373 public function testCreateNameIndividual() {
375 'first_name' => 'abc1',
376 'contact_type' => 'Individual',
377 'last_name' => 'xyz1',
380 $this->callAPISuccess('contact', 'create', $params);
384 * Test creating individual by display_name.
386 * Display name & sort name should be set.
388 public function testCreateDisplayNameIndividual() {
390 'display_name' => 'abc1',
391 'contact_type' => 'Individual',
394 $contact = $this->callAPISuccess('contact', 'create', $params);
395 $params['sort_name'] = 'abc1';
396 $this->getAndCheck($params, $contact['id'], 'contact');
400 * Test that name searches are case insensitive.
402 public function testGetNameVariantsCaseInsensitive() {
403 $this->callAPISuccess('contact', 'create', [
404 'display_name' => 'Abc1',
405 'contact_type' => 'Individual',
407 $this->callAPISuccessGetSingle('Contact', ['display_name' => 'aBc1']);
408 $this->callAPISuccessGetSingle('Contact', ['sort_name' => 'aBc1']);
409 Civi
::settings()->set('includeNickNameInName', TRUE);
410 $this->callAPISuccessGetSingle('Contact', ['display_name' => 'aBc1']);
411 $this->callAPISuccessGetSingle('Contact', ['sort_name' => 'aBc1']);
412 Civi
::settings()->set('includeNickNameInName', FALSE);
416 * Test old keys still work.
418 * Verify that attempt to create individual contact with
419 * first and last names and old key values works
421 public function testCreateNameIndividualOldKeys() {
423 'individual_prefix' => 'Dr.',
424 'first_name' => 'abc1',
425 'contact_type' => 'Individual',
426 'last_name' => 'xyz1',
427 'individual_suffix' => 'Jr.',
430 $contact = $this->callAPISuccess('contact', 'create', $params);
431 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
433 $this->assertArrayKeyExists('prefix_id', $result);
434 $this->assertArrayKeyExists('suffix_id', $result);
435 $this->assertArrayKeyExists('gender_id', $result);
436 $this->assertEquals(4, $result['prefix_id']);
437 $this->assertEquals(1, $result['suffix_id']);
441 * Test preferred keys work.
443 * Verify that attempt to create individual contact with
444 * first and last names and old key values works
446 public function testCreateNameIndividualRecommendedKeys2() {
448 'prefix_id' => 'Dr.',
449 'first_name' => 'abc1',
450 'contact_type' => 'Individual',
451 'last_name' => 'xyz1',
452 'suffix_id' => 'Jr.',
453 'gender_id' => 'Male',
456 $contact = $this->callAPISuccess('contact', 'create', $params);
457 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
459 $this->assertArrayKeyExists('prefix_id', $result);
460 $this->assertArrayKeyExists('suffix_id', $result);
461 $this->assertArrayKeyExists('gender_id', $result);
462 $this->assertEquals(4, $result['prefix_id']);
463 $this->assertEquals(1, $result['suffix_id']);
467 * Test household name is sufficient for create.
469 * Verify that attempt to create household contact with only
470 * household name succeeds
472 public function testCreateNameHousehold() {
474 'household_name' => 'The abc Household',
475 'contact_type' => 'Household',
477 $this->callAPISuccess('contact', 'create', $params);
481 * Test organization name is sufficient for create.
483 * Verify that attempt to create organization contact with only
484 * organization name succeeds.
486 public function testCreateNameOrganization() {
488 'organization_name' => 'The abc Organization',
489 'contact_type' => 'Organization',
491 $this->callAPISuccess('contact', 'create', $params);
495 * Verify that attempt to create organization contact without organization name fails.
497 public function testCreateNoNameOrganization() {
499 'first_name' => 'The abc Organization',
500 'contact_type' => 'Organization',
502 $this->callAPIFailure('contact', 'create', $params);
506 * Check that permissions on API key are restricted (CRM-18112).
508 public function testCreateApiKey() {
509 $config = CRM_Core_Config
::singleton();
510 $contactId = $this->individualCreate(array(
515 // Allow edit -- because permissions aren't being checked
516 $config->userPermissionClass
->permissions
= array();
517 $result = $this->callAPISuccess('Contact', 'create', array(
519 'api_key' => 'original',
521 $this->assertEquals('original', $result['values'][$contactId]['api_key']);
523 // Allow edit -- because we have adequate permission
524 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'edit all contacts', 'edit api keys');
525 $result = $this->callAPISuccess('Contact', 'create', array(
526 'check_permissions' => 1,
528 'api_key' => 'abcd1234',
530 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
532 // Disallow edit -- because we don't have permission
533 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'edit all contacts');
534 $result = $this->callAPIFailure('Contact', 'create', array(
535 'check_permissions' => 1,
537 'api_key' => 'defg4321',
539 $this->assertRegExp(';Permission denied to modify api key;', $result['error_message']);
541 // Return everything -- because permissions are not being checked
542 $config->userPermissionClass
->permissions
= array();
543 $result = $this->callAPISuccess('Contact', 'create', array(
545 'first_name' => 'A2',
547 $this->assertEquals('A2', $result['values'][$contactId]['first_name']);
548 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
549 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
551 // Return everything -- because we have adequate permission
552 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'edit all contacts', 'edit api keys');
553 $result = $this->callAPISuccess('Contact', 'create', array(
554 'check_permissions' => 1,
556 'first_name' => 'A3',
558 $this->assertEquals('A3', $result['values'][$contactId]['first_name']);
559 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
560 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
562 // Restricted return -- because we don't have permission
563 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'edit all contacts');
564 $result = $this->callAPISuccess('Contact', 'create', array(
565 'check_permissions' => 1,
567 'first_name' => 'A4',
569 $this->assertEquals('A4', $result['values'][$contactId]['first_name']);
570 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
571 $this->assertTrue(empty($result['values'][$contactId]['api_key']));
575 * Check with complete array + custom field.
577 * Note that the test is written on purpose without any
578 * variables specific to participant so it can be replicated into other entities
579 * and / or moved to the automated test suite
581 public function testCreateWithCustom() {
582 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
584 $params = $this->_params
;
585 $params['custom_' . $ids['custom_field_id']] = "custom string";
586 $description = "This demonstrates setting a custom field through the API.";
587 $result = $this->callAPIAndDocument($this->_entity
, 'create', $params, __FUNCTION__
, __FILE__
, $description);
589 $check = $this->callAPISuccess($this->_entity
, 'get', array(
590 'return.custom_' . $ids['custom_field_id'] => 1,
591 'id' => $result['id'],
593 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
595 $this->customFieldDelete($ids['custom_field_id']);
596 $this->customGroupDelete($ids['custom_group_id']);
600 * CRM-12773 - expectation is that civicrm quietly ignores fields without values.
602 public function testCreateWithNULLCustomCRM12773() {
603 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
604 $params = $this->_params
;
605 $params['custom_' . $ids['custom_field_id']] = NULL;
606 $this->callAPISuccess('contact', 'create', $params);
607 $this->customFieldDelete($ids['custom_field_id']);
608 $this->customGroupDelete($ids['custom_group_id']);
612 * CRM-14232 test preferred language set to site default if not passed.
614 public function testCreatePreferredLanguageUnset() {
615 $this->callAPISuccess('Contact', 'create', array(
616 'first_name' => 'Snoop',
617 'last_name' => 'Dog',
618 'contact_type' => 'Individual')
620 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
621 $this->assertEquals('en_US', $result['preferred_language']);
625 * CRM-14232 test preferred language returns setting if not passed.
627 public function testCreatePreferredLanguageSet() {
628 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'fr_FR'));
629 $this->callAPISuccess('Contact', 'create', array(
630 'first_name' => 'Snoop',
631 'last_name' => 'Dog',
632 'contact_type' => 'Individual',
634 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
635 $this->assertEquals('fr_FR', $result['preferred_language']);
639 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
641 public function testCreatePreferredLanguageNull() {
642 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
643 $this->callAPISuccess('Contact', 'create', array(
644 'first_name' => 'Snoop',
645 'last_name' => 'Dog',
646 'contact_type' => 'Individual',
649 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
650 $this->assertEquals(NULL, $result['preferred_language']);
654 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
656 public function testCreatePreferredLanguagePassed() {
657 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
658 $this->callAPISuccess('Contact', 'create', array(
659 'first_name' => 'Snoop',
660 'last_name' => 'Dog',
661 'contact_type' => 'Individual',
662 'preferred_language' => 'en_AU',
664 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
665 $this->assertEquals('en_AU', $result['preferred_language']);
669 * CRM-15792 - create/update datetime field for contact.
671 public function testCreateContactCustomFldDateTime() {
672 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'datetime_test_group'));
673 $dateTime = CRM_Utils_Date
::currentDBDate();
674 //check date custom field is saved along with time when time_format is set
676 'first_name' => 'abc3',
677 'last_name' => 'xyz3',
678 'contact_type' => 'Individual',
679 'email' => 'man3@yahoo.com',
680 'api.CustomField.create' => array(
681 'custom_group_id' => $customGroup['id'],
682 'name' => 'test_datetime',
683 'label' => 'Demo Date',
684 'html_type' => 'Select Date',
685 'data_type' => 'Date',
689 'is_searchable' => 0,
694 $result = $this->callAPISuccess('Contact', 'create', $params);
695 $customFldId = $result['values'][$result['id']]['api.CustomField.create']['id'];
696 $this->assertNotNull($result['id']);
697 $this->assertNotNull($customFldId);
700 'id' => $result['id'],
701 "custom_{$customFldId}" => $dateTime,
702 'api.CustomValue.get' => 1,
705 $result = $this->callAPISuccess('Contact', 'create', $params);
706 $this->assertNotNull($result['id']);
707 $customFldDate = date("YmdHis", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
708 $this->assertNotNull($customFldDate);
709 $this->assertEquals($dateTime, $customFldDate);
710 $customValueId = $result['values'][$result['id']]['api.CustomValue.get']['values'][0]['id'];
711 $dateTime = date('Ymd');
712 //date custom field should not contain time part when time_format is null
714 'id' => $result['id'],
715 'api.CustomField.create' => array(
716 'id' => $customFldId,
717 'html_type' => 'Select Date',
718 'data_type' => 'Date',
721 'api.CustomValue.create' => array(
722 'id' => $customValueId,
723 'entity_id' => $result['id'],
724 "custom_{$customFldId}" => $dateTime,
726 'api.CustomValue.get' => 1,
728 $result = $this->callAPISuccess('Contact', 'create', $params);
729 $this->assertNotNull($result['id']);
730 $customFldDate = date("Ymd", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
731 $customFldTime = date("His", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
732 $this->assertNotNull($customFldDate);
733 $this->assertEquals($dateTime, $customFldDate);
734 $this->assertEquals(000000, $customFldTime);
735 $this->callAPISuccess('Contact', 'create', $params);
740 * Test creating a current employer through API.
742 public function testContactCreateCurrentEmployer() {
743 // Here we will just do the get for set-up purposes.
744 $count = $this->callAPISuccess('contact', 'getcount', array(
745 'organization_name' => 'new employer org',
746 'contact_type' => 'Organization',
748 $this->assertEquals(0, $count);
749 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
750 'current_employer' => 'new employer org',
753 // do it again as an update to check it doesn't cause an error
754 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
755 'current_employer' => 'new employer org',
756 'id' => $employerResult['id'],
760 $this->callAPISuccess('contact', 'getcount', array(
761 'organization_name' => 'new employer org',
762 'contact_type' => 'Organization',
766 $result = $this->callAPISuccess('contact', 'getsingle', array(
767 'id' => $employerResult['id'],
770 $this->assertEquals('new employer org', $result['current_employer']);
775 * Test creating a current employer through API.
777 * Check it will re-activate a de-activated employer
779 public function testContactCreateDuplicateCurrentEmployerEnables() {
780 // Set up - create employer relationship.
781 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
782 'current_employer' => 'new employer org',
785 $relationship = $this->callAPISuccess('relationship', 'get', array(
786 'contact_id_a' => $employerResult['id'],
789 //disable & check it is disabled
790 $this->callAPISuccess('relationship', 'create', array('id' => $relationship['id'], 'is_active' => 0));
791 $this->callAPISuccess('relationship', 'getvalue', array(
792 'id' => $relationship['id'],
793 'return' => 'is_active',
796 // Re-set the current employer - thus enabling the relationship.
797 $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
798 'current_employer' => 'new employer org',
799 'id' => $employerResult['id'],
802 //check is_active is now 1
803 $relationship = $this->callAPISuccess('relationship', 'getsingle', array(
804 'return' => 'is_active',
806 $this->assertEquals(1, $relationship['is_active']);
810 * Check deceased contacts are not retrieved.
812 * Note at time of writing the default is to return default. This should possibly be changed & test added.
814 public function testGetDeceasedRetrieved() {
815 $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
816 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
817 'first_name' => 'bb',
818 'last_name' => 'ccc',
819 'contact_type' => 'Individual',
822 $result = $this->callAPISuccess($this->_entity
, 'get', array('is_deceased' => 0));
823 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
827 * Test that sort works - old syntax.
829 public function testGetSort() {
830 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
831 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
832 'first_name' => 'bb',
833 'last_name' => 'ccc',
834 'contact_type' => 'Individual',
836 $result = $this->callAPISuccess($this->_entity
, 'get', array(
837 'sort' => 'first_name ASC',
838 'return.first_name' => 1,
841 'contact_type' => 'Individual',
844 $this->assertEquals('abc1', $result['values'][0]['first_name']);
845 $result = $this->callAPISuccess($this->_entity
, 'get', array(
846 'sort' => 'first_name DESC',
847 'return.first_name' => 1,
851 $this->assertEquals('bb', $result['values'][0]['first_name']);
853 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
854 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
858 * Test that we can retrieve contacts using array syntax.
860 * I.e 'id' => array('IN' => array('3,4')).
862 public function testGetINIDArray() {
863 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
864 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
865 'first_name' => 'bb',
866 'last_name' => 'ccc',
867 'contact_type' => 'Individual',
869 $c3 = $this->callAPISuccess($this->_entity
, 'create', array(
870 'first_name' => 'hh',
872 'contact_type' => 'Individual',
874 $result = $this->callAPISuccess($this->_entity
, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
875 $this->assertEquals(2, $result['count']);
876 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
877 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
878 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
879 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c3['id']));
883 * Test variants on deleted behaviour.
885 public function testGetDeleted() {
886 $params = $this->_params
;
887 $contact1 = $this->callAPISuccess('contact', 'create', $params);
888 $params['is_deleted'] = 1;
889 $params['last_name'] = 'bcd';
890 $contact2 = $this->callAPISuccess('contact', 'create', $params);
891 $countActive = $this->callAPISuccess('contact', 'getcount', array(
892 'showAll' => 'active',
893 'contact_type' => 'Individual',
895 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all', 'contact_type' => 'Individual'));
896 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash', 'contact_type' => 'Individual'));
897 $countDefault = $this->callAPISuccess('contact', 'getcount', array('contact_type' => 'Individual'));
898 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
899 'contact_type' => 'Individual',
900 'contact_is_deleted' => 1,
902 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
903 'contact_is_deleted' => 0,
904 'contact_type' => 'Individual',
906 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
907 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
908 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected');
909 $this->assertEquals(1, $countActive);
910 $this->assertEquals(1, $countTrash);
911 $this->assertEquals(2, $countAll);
912 $this->assertEquals(1, $countDeleted);
913 $this->assertEquals(1, $countDefault, 'Only active by default in line');
917 * Test that sort works - new syntax.
919 public function testGetSortNewSyntax() {
920 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
921 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
922 'first_name' => 'bb',
923 'last_name' => 'ccc',
924 'contact_type' => 'Individual',
926 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
927 'return' => 'first_name',
928 'contact_type' => 'Individual',
931 'sort' => 'first_name',
934 $this->assertEquals('abc1', $result);
936 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
937 'return' => 'first_name',
938 'contact_type' => 'Individual',
941 'sort' => 'first_name DESC',
944 $this->assertEquals('bb', $result);
946 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
947 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
951 * Test sort and limit for chained relationship get.
953 * https://issues.civicrm.org/jira/browse/CRM-15983
955 public function testSortLimitChainedRelationshipGetCRM15983() {
957 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
958 'first_name' => 'Jules',
959 'last_name' => 'Smos',
960 'contact_type' => 'Individual',
963 // Create another contact with two relationships.
964 $create_params = array(
965 'first_name' => 'Jos',
966 'last_name' => 'Smos',
967 'contact_type' => 'Individual',
968 'api.relationship.create' => array(
970 'contact_id_a' => '$value.id',
971 'contact_id_b' => $create_result_1['id'],
973 'relationship_type_id' => 2,
974 'start_date' => '2005-01-12',
975 'end_date' => '2006-01-11',
976 'description' => 'old',
979 'contact_id_a' => '$value.id',
980 'contact_id_b' => $create_result_1['id'],
981 // spouse of (was married twice :))
982 'relationship_type_id' => 2,
983 'start_date' => '2006-07-01',
984 'end_date' => '2010-07-01',
985 'description' => 'new',
989 $create_result = $this->callAPISuccess('contact', 'create', $create_params);
991 // Try to retrieve the contact and the most recent relationship.
994 'id' => $create_result['id'],
995 'api.relationship.get' => array(
996 'contact_id_a' => '$value.id',
999 'sort' => 'start_date DESC',
1002 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
1005 $this->callAPISuccess('contact', 'delete', array(
1006 'id' => $create_result['id'],
1010 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
1011 $this->assertEquals('new', $get_result['api.relationship.get']['values'][0]['description']);
1015 * Test apostrophe works in get & create.
1017 public function testGetApostropheCRM10857() {
1018 $params = array_merge($this->_params
, array('last_name' => "O'Connor"));
1019 $this->callAPISuccess($this->_entity
, 'create', $params);
1020 $result = $this->callAPISuccess($this->_entity
, 'getsingle', array(
1021 'last_name' => "O'Connor",
1024 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__
);
1028 * Test retrieval by addressee id.
1030 public function testGetByAddresseeID() {
1031 $individual1ID = $this->individualCreate([
1032 'skip_greeting_processing' => 1,
1033 'addressee_id' => 'null',
1034 'email_greeting_id' => 'null',
1035 'postal_greeting_id' => 'null'
1037 $individual2ID = $this->individualCreate();
1039 $this->assertEquals($individual1ID,
1040 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'addressee_id' => ['IS NULL' => 1], 'return' => 'id'])
1042 $this->assertEquals($individual1ID,
1043 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'email_greeting_id' => ['IS NULL' => 1], 'return' => 'id'])
1045 $this->assertEquals($individual1ID,
1046 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'postal_greeting_id' => ['IS NULL' => 1], 'return' => 'id'])
1049 $this->assertEquals($individual2ID,
1050 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'addressee_id' => ['NOT NULL' => 1], 'return' => 'id'])
1055 * Check with complete array + custom field.
1057 * Note that the test is written on purpose without any
1058 * variables specific to participant so it can be replicated into other entities
1059 * and / or moved to the automated test suite
1061 public function testGetWithCustom() {
1062 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1064 $params = $this->_params
;
1065 $params['custom_' . $ids['custom_field_id']] = "custom string";
1066 $description = "This demonstrates setting a custom field through the API.";
1067 $subfile = "CustomFieldGet";
1068 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
1070 $check = $this->callAPIAndDocument($this->_entity
, 'get', array(
1071 'return.custom_' . $ids['custom_field_id'] => 1,
1072 'id' => $result['id'],
1073 ), __FUNCTION__
, __FILE__
, $description, $subfile);
1075 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
1076 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
1077 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
1078 $this->customFieldDelete($ids['custom_field_id']);
1079 $this->customGroupDelete($ids['custom_group_id']);
1083 * Check with complete array + custom field.
1085 * Note that the test is written on purpose without any
1086 * variables specific to participant so it can be replicated into other entities
1087 * and / or moved to the automated test suite
1089 public function testGetWithCustomReturnSyntax() {
1090 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1092 $params = $this->_params
;
1093 $params['custom_' . $ids['custom_field_id']] = "custom string";
1094 $description = "This demonstrates setting a custom field through the API.";
1095 $subfile = "CustomFieldGetReturnSyntaxVariation";
1096 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
1097 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
1098 $check = $this->callAPIAndDocument($this->_entity
, 'get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1100 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
1101 $this->customFieldDelete($ids['custom_field_id']);
1102 $this->customGroupDelete($ids['custom_group_id']);
1106 * Check that address name, ID is returned if required.
1108 public function testGetReturnAddress() {
1109 $contactID = $this->individualCreate();
1110 $result = $this->callAPISuccess('address', 'create', array(
1111 'contact_id' => $contactID,
1112 'address_name' => 'My house',
1113 'location_type_id' => 'Home',
1114 'street_address' => '1 my road',
1116 $addressID = $result['id'];
1118 $result = $this->callAPISuccessGetSingle('contact', array(
1119 'return' => 'address_name, street_address, address_id',
1122 $this->assertEquals($addressID, $result['address_id']);
1123 $this->assertEquals('1 my road', $result['street_address']);
1124 $this->assertEquals('My house', $result['address_name']);
1129 * Test group filter syntaxes.
1131 public function testGetGroupIDFromContact() {
1132 $groupId = $this->groupCreate();
1134 'email' => 'man2@yahoo.com',
1135 'contact_type' => 'Individual',
1136 'location_type_id' => 1,
1137 'api.group_contact.create' => array('group_id' => $groupId),
1140 $this->callAPISuccess('contact', 'create', $params);
1141 // testing as integer
1143 'filter.group_id' => $groupId,
1144 'contact_type' => 'Individual',
1146 $result = $this->callAPISuccess('contact', 'get', $params);
1147 $this->assertEquals(1, $result['count']);
1148 // group 26 doesn't exist, but we can still search contacts in it.
1150 'filter.group_id' => 26,
1151 'contact_type' => 'Individual',
1153 $this->callAPISuccess('contact', 'get', $params);
1154 // testing as string
1156 'filter.group_id' => "$groupId, 26",
1157 'contact_type' => 'Individual',
1159 $result = $this->callAPISuccess('contact', 'get', $params);
1160 $this->assertEquals(1, $result['count']);
1162 'filter.group_id' => "26,27",
1163 'contact_type' => 'Individual',
1165 $this->callAPISuccess('contact', 'get', $params);
1167 // testing as string
1169 'filter.group_id' => array($groupId, 26),
1170 'contact_type' => 'Individual',
1172 $result = $this->callAPISuccess('contact', 'get', $params);
1173 $this->assertEquals(1, $result['count']);
1175 //test in conjunction with other criteria
1177 'filter.group_id' => array($groupId, 26),
1178 'contact_type' => 'Organization',
1180 $this->callAPISuccess('contact', 'get', $params);
1182 'filter.group_id' => array(26, 27),
1183 'contact_type' => 'Individual',
1185 $result = $this->callAPISuccess('contact', 'get', $params);
1186 $this->assertEquals(0, $result['count']);
1190 * Verify that attempt to create individual contact with two chained websites succeeds.
1192 public function testCreateIndividualWithContributionDottedSyntax() {
1193 $description = "This demonstrates the syntax to create 2 chained entities.";
1194 $subFile = "ChainTwoWebsites";
1196 'first_name' => 'abc3',
1197 'last_name' => 'xyz3',
1198 'contact_type' => 'Individual',
1199 'email' => 'man3@yahoo.com',
1200 'api.contribution.create' => array(
1201 'receive_date' => '2010-01-01',
1202 'total_amount' => 100.00,
1203 'financial_type_id' => $this->_financialTypeId
,
1204 'payment_instrument_id' => 1,
1205 'non_deductible_amount' => 10.00,
1206 'fee_amount' => 50.00,
1207 'net_amount' => 90.00,
1209 'invoice_id' => 67990,
1211 'contribution_status_id' => 1,
1212 'skipCleanMoney' => 1,
1214 'api.website.create' => array(
1215 'url' => "http://civicrm.org",
1217 'api.website.create.2' => array(
1218 'url' => "http://chained.org",
1222 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
1224 // checking child function result not covered in callAPIAndDocument
1225 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
1226 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url']);
1227 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url']);
1229 // delete the contact
1230 $this->callAPISuccess('contact', 'delete', $result);
1234 * Verify that attempt to create individual contact with chained contribution and website succeeds.
1236 public function testCreateIndividualWithContributionChainedArrays() {
1238 'first_name' => 'abc3',
1239 'last_name' => 'xyz3',
1240 'contact_type' => 'Individual',
1241 'email' => 'man3@yahoo.com',
1242 'api.contribution.create' => array(
1243 'receive_date' => '2010-01-01',
1244 'total_amount' => 100.00,
1245 'financial_type_id' => $this->_financialTypeId
,
1246 'payment_instrument_id' => 1,
1247 'non_deductible_amount' => 10.00,
1248 'fee_amount' => 50.00,
1249 'net_amount' => 90.00,
1251 'invoice_id' => 67890,
1253 'contribution_status_id' => 1,
1254 'skipCleanMoney' => 1,
1256 'api.website.create' => array(
1258 'url' => "http://civicrm.org",
1261 'url' => "http://chained.org",
1262 'website_type_id' => 2,
1267 $description = "Demonstrates creating two websites as an array.";
1268 $subfile = "ChainTwoWebsitesSyntax2";
1269 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1271 // the callAndDocument doesn't check the chained call
1272 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error']);
1273 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url']);
1274 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url']);
1276 $this->callAPISuccess('contact', 'delete', $result);
1280 * Test for direction when chaining relationships.
1282 * https://issues.civicrm.org/jira/browse/CRM-16084
1284 public function testDirectionChainingRelationshipsCRM16084() {
1285 // Some contact, called Jules.
1286 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
1287 'first_name' => 'Jules',
1288 'last_name' => 'Smos',
1289 'contact_type' => 'Individual',
1292 // Another contact: Jos, child of Jules.
1293 $create_params = array(
1294 'first_name' => 'Jos',
1295 'last_name' => 'Smos',
1296 'contact_type' => 'Individual',
1297 'api.relationship.create' => array(
1299 'contact_id_a' => '$value.id',
1300 'contact_id_b' => $create_result_1['id'],
1302 'relationship_type_id' => 1,
1306 $create_result_2 = $this->callAPISuccess('contact', 'create', $create_params);
1308 // Mia is the child of Jos.
1309 $create_params = array(
1310 'first_name' => 'Mia',
1311 'last_name' => 'Smos',
1312 'contact_type' => 'Individual',
1313 'api.relationship.create' => array(
1315 'contact_id_a' => '$value.id',
1316 'contact_id_b' => $create_result_2['id'],
1318 'relationship_type_id' => 1,
1322 $create_result_3 = $this->callAPISuccess('contact', 'create', $create_params);
1324 // Get Jos and his children.
1325 $get_params = array(
1327 'id' => $create_result_2['id'],
1328 'api.relationship.get' => array(
1329 'contact_id_b' => '$value.id',
1330 'relationship_type_id' => 1,
1333 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
1336 $this->callAPISuccess('contact', 'delete', array(
1337 'id' => $create_result_1['id'],
1339 $this->callAPISuccess('contact', 'delete', array(
1340 'id' => $create_result_2['id'],
1342 $this->callAPISuccess('contact', 'delete', array(
1343 'id' => $create_result_2['id'],
1347 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
1348 $this->assertEquals($create_result_3['id'], $get_result['api.relationship.get']['values'][0]['contact_id_a']);
1352 * Verify that attempt to create individual contact with first, and last names and email succeeds.
1354 public function testCreateIndividualWithNameEmail() {
1356 'first_name' => 'abc3',
1357 'last_name' => 'xyz3',
1358 'contact_type' => 'Individual',
1359 'email' => 'man3@yahoo.com',
1362 $contact = $this->callAPISuccess('contact', 'create', $params);
1364 $this->callAPISuccess('contact', 'delete', $contact);
1368 * Verify that attempt to create individual contact with no data fails.
1370 public function testCreateIndividualWithOutNameEmail() {
1372 'contact_type' => 'Individual',
1374 $this->callAPIFailure('contact', 'create', $params);
1378 * Test create individual contact with first &last names, email and location type succeeds.
1380 public function testCreateIndividualWithNameEmailLocationType() {
1382 'first_name' => 'abc4',
1383 'last_name' => 'xyz4',
1384 'email' => 'man4@yahoo.com',
1385 'contact_type' => 'Individual',
1386 'location_type_id' => 1,
1388 $result = $this->callAPISuccess('contact', 'create', $params);
1390 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
1394 * Verify that when changing employers the old employer relationship becomes inactive.
1396 public function testCreateIndividualWithEmployer() {
1397 $employer = $this->organizationCreate();
1398 $employer2 = $this->organizationCreate();
1401 'email' => 'man4@yahoo.com',
1402 'contact_type' => 'Individual',
1403 'employer_id' => $employer,
1406 $result = $this->callAPISuccess('contact', 'create', $params);
1407 $relationships = $this->callAPISuccess('relationship', 'get', array(
1408 'contact_id_a' => $result['id'],
1412 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1414 // Add more random relationships to make the test more realistic
1415 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
1416 $relTypeId = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
1417 $this->callAPISuccess('relationship', 'create', array(
1418 'contact_id_a' => $result['id'],
1419 'contact_id_b' => $this->organizationCreate(),
1421 'relationship_type_id' => $relTypeId,
1425 // Add second employer
1426 $params['employer_id'] = $employer2;
1427 $params['id'] = $result['id'];
1428 $result = $this->callAPISuccess('contact', 'create', $params);
1430 $relationships = $this->callAPISuccess('relationship', 'get', array(
1431 'contact_id_a' => $result['id'],
1436 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1440 * Verify that attempt to create household contact with details succeeds.
1442 public function testCreateHouseholdDetails() {
1444 'household_name' => 'abc8\'s House',
1445 'nick_name' => 'x House',
1446 'email' => 'man8@yahoo.com',
1447 'contact_type' => 'Household',
1450 $contact = $this->callAPISuccess('contact', 'create', $params);
1452 $this->callAPISuccess('contact', 'delete', $contact);
1456 * Verify that attempt to create household contact with inadequate details fails.
1458 public function testCreateHouseholdInadequateDetails() {
1460 'nick_name' => 'x House',
1461 'email' => 'man8@yahoo.com',
1462 'contact_type' => 'Household',
1464 $this->callAPIFailure('contact', 'create', $params);
1468 * Verify successful update of individual contact.
1470 public function testUpdateIndividualWithAll() {
1471 // Insert a row in civicrm_contact creating individual contact.
1472 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1473 $op->execute($this->_dbconn
,
1474 $this->createXMLDataSet(
1475 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1481 'first_name' => 'abcd',
1482 'contact_type' => 'Individual',
1483 'nick_name' => 'This is nickname first',
1484 'do_not_email' => '1',
1485 'do_not_phone' => '1',
1486 'do_not_mail' => '1',
1487 'do_not_trade' => '1',
1488 'legal_identifier' => 'ABC23853ZZ2235',
1489 'external_identifier' => '1928837465',
1490 'image_URL' => 'http://some.url.com/image.jpg',
1491 'home_url' => 'http://www.example.org',
1495 $this->callAPISuccess('Contact', 'Update', $params);
1496 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
1497 unset($params['contact_id']);
1498 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
1499 //reducing this test partially back to api v2 level to get it through
1500 unset($params['home_url']);
1501 foreach ($params as $key => $value) {
1502 $this->assertEquals($value, $getResult['values'][23][$key]);
1504 // Check updated civicrm_contact against expected.
1505 $expected = $this->createXMLDataSet(
1506 dirname(__FILE__
) . '/dataset/contact_ind_upd.xml'
1508 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1511 $actual->addTable('civicrm_contact');
1512 $expected->matches($actual);
1516 * Verify successful update of organization contact.
1518 public function testUpdateOrganizationWithAll() {
1519 // Insert a row in civicrm_contact creating organization contact
1520 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1521 $op->execute($this->_dbconn
,
1522 $this->createXMLDataSet(
1523 dirname(__FILE__
) . '/dataset/contact_org.xml'
1529 'organization_name' => 'WebAccess India Pvt Ltd',
1530 'legal_name' => 'WebAccess',
1531 'sic_code' => 'ABC12DEF',
1532 'contact_type' => 'Organization',
1535 $this->callAPISuccess('Contact', 'Update', $params);
1537 // Check updated civicrm_contact against expected.
1538 $expected = $this->createXMLDataSet(
1539 dirname(__FILE__
) . '/dataset/contact_org_upd.xml'
1541 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1544 $actual->addTable('civicrm_contact');
1545 $expected->matches($actual);
1549 * Test merging 2 organizations.
1551 * CRM-20421: This test make sure that inherited memberships are deleted upon merging organization.
1553 public function testMergeOrganizations() {
1554 $organizationID1 = $this->organizationCreate(array(), 0);
1555 $organizationID2 = $this->organizationCreate(array(), 1);
1556 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
1557 'employer_id' => $organizationID1,
1560 $contact = $contact["values"][$contact["id"]];
1562 $membershipType = $this->createEmployerOfMembership();
1563 $membershipParams = array(
1564 'membership_type_id' => $membershipType["id"],
1565 'contact_id' => $organizationID1,
1566 'start_date' => "01/01/2015",
1567 'join_date' => "01/01/2010",
1568 'end_date' => "12/31/2015",
1570 $ownermembershipid = $this->contactMembershipCreate($membershipParams);
1572 $contactmembership = $this->callAPISuccess("membership", "getsingle", array(
1573 "contact_id" => $contact["id"],
1576 $this->assertEquals($ownermembershipid, $contactmembership["owner_membership_id"], "Contact membership must be inherited from Organization");
1578 CRM_Dedupe_Merger
::moveAllBelongings($organizationID2, $organizationID1, array(
1579 "move_rel_table_memberships" => "0",
1580 "move_rel_table_relationships" => "1",
1581 "main_details" => array(
1582 "contact_id" => $organizationID2,
1583 "contact_type" => "Organization",
1585 "other_details" => array(
1586 "contact_id" => $organizationID1,
1587 "contact_type" => "Organization",
1591 $contactmembership = $this->callAPISuccess("membership", "get", array(
1592 "contact_id" => $contact["id"],
1595 $this->assertEquals(0, $contactmembership["count"], "Contact membership must be deleted after merging organization without memberships.");
1598 private function createEmployerOfMembership() {
1600 'domain_id' => CRM_Core_Config
::domainID(),
1601 'name' => 'Organization Membership',
1602 'description' => NULL,
1603 'member_of_contact_id' => 1,
1604 'financial_type_id' => 1,
1605 'minimum_fee' => 10,
1606 'duration_unit' => 'year',
1607 'duration_interval' => 1,
1608 'period_type' => 'rolling',
1609 'relationship_type_id' => 5,
1610 'relationship_direction' => 'b_a',
1611 'visibility' => 'Public',
1614 $membershipType = $this->callAPISuccess('membership_type', 'create', $params);
1615 return $membershipType["values"][$membershipType["id"]];
1619 * Verify successful update of household contact.
1621 public function testUpdateHouseholdWithAll() {
1622 // Insert a row in civicrm_contact creating household contact
1623 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1624 $op->execute($this->_dbconn
,
1625 $this->createXMLDataSet(
1626 dirname(__FILE__
) . '/dataset/contact_hld.xml'
1632 'household_name' => 'ABC household',
1633 'nick_name' => 'ABC House',
1634 'contact_type' => 'Household',
1637 $result = $this->callAPISuccess('Contact', 'Update', $params);
1640 'contact_type' => 'Household',
1642 'sort_name' => 'ABC household',
1643 'display_name' => 'ABC household',
1644 'nick_name' => 'ABC House',
1646 $this->getAndCheck($expected, $result['id'], 'contact');
1650 * Test civicrm_update() without contact type.
1652 * Deliberately exclude contact_type as it should still cope using civicrm_api.
1656 public function testUpdateCreateWithID() {
1657 // Insert a row in civicrm_contact creating individual contact.
1658 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1659 $op->execute($this->_dbconn
,
1660 $this->createXMLDataSet(
1661 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1667 'first_name' => 'abcd',
1668 'last_name' => 'wxyz',
1670 $this->callAPISuccess('Contact', 'Update', $params);
1674 * Test civicrm_contact_delete() with no contact ID.
1676 public function testContactDeleteNoID() {
1680 $this->callAPIFailure('contact', 'delete', $params);
1684 * Test civicrm_contact_delete() with error.
1686 public function testContactDeleteError() {
1687 $params = array('contact_id' => 999);
1688 $this->callAPIFailure('contact', 'delete', $params);
1692 * Test civicrm_contact_delete().
1694 public function testContactDelete() {
1695 $contactID = $this->individualCreate();
1699 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__
, __FILE__
);
1703 * Test civicrm_contact_get() return only first name.
1705 public function testContactGetRetFirst() {
1706 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1708 'contact_id' => $contact['id'],
1709 'return_first_name' => TRUE,
1710 'sort' => 'first_name',
1712 $result = $this->callAPISuccess('contact', 'get', $params);
1713 $this->assertEquals(1, $result['count']);
1714 $this->assertEquals($contact['id'], $result['id']);
1715 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1719 * Test civicrm_contact_get() return only first name & last name.
1721 * Use comma separated string return with a space.
1723 public function testContactGetReturnFirstLast() {
1724 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1726 'contact_id' => $contact['id'],
1727 'return' => 'first_name, last_name',
1729 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1730 $this->assertEquals('abc1', $result['first_name']);
1731 $this->assertEquals('xyz1', $result['last_name']);
1732 //check that other defaults not returns
1733 $this->assertArrayNotHasKey('sort_name', $result);
1735 'contact_id' => $contact['id'],
1736 'return' => 'first_name,last_name',
1738 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1739 $this->assertEquals('abc1', $result['first_name']);
1740 $this->assertEquals('xyz1', $result['last_name']);
1741 //check that other defaults not returns
1742 $this->assertArrayNotHasKey('sort_name', $result);
1746 * Test civicrm_contact_get() return only first name & last name.
1748 * Use comma separated string return without a space
1750 public function testContactGetReturnFirstLastNoComma() {
1751 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1753 'contact_id' => $contact['id'],
1754 'return' => 'first_name,last_name',
1756 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1757 $this->assertEquals('abc1', $result['first_name']);
1758 $this->assertEquals('xyz1', $result['last_name']);
1759 //check that other defaults not returns
1760 $this->assertArrayNotHasKey('sort_name', $result);
1764 * Test civicrm_contact_get() with default return properties.
1766 public function testContactGetRetDefault() {
1767 $contactID = $this->individualCreate();
1769 'contact_id' => $contactID,
1770 'sort' => 'first_name',
1772 $result = $this->callAPISuccess('contact', 'get', $params);
1773 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1774 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1778 * Test civicrm_contact_getquick() with empty name param.
1780 public function testContactGetQuick() {
1781 // Insert a row in civicrm_contact creating individual contact.
1782 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1783 $op->execute($this->_dbconn
,
1784 $this->createXMLDataSet(
1785 dirname(__FILE__
) . '/dataset/contact_17.xml'
1788 $op->execute($this->_dbconn
,
1789 $this->createXMLDataSet(
1790 dirname(__FILE__
) . '/dataset/email_contact_17.xml'
1797 $result = $this->callAPISuccess('contact', 'getquick', $params);
1798 $this->assertEquals(17, $result['values'][0]['id']);
1802 * Test civicrm_contact_get) with empty params.
1804 public function testContactGetEmptyParams() {
1805 $this->callAPISuccess('contact', 'get', array());
1809 * Test civicrm_contact_get(,true) with no matches.
1811 public function testContactGetOldParamsNoMatches() {
1812 // Insert a row in civicrm_contact creating contact 17.
1813 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1814 $op->execute($this->_dbconn
,
1815 $this->createXMLDataSet(
1816 dirname(__FILE__
) . '/dataset/contact_17.xml'
1821 'first_name' => 'Fred',
1823 $result = $this->callAPISuccess('contact', 'get', $params);
1824 $this->assertEquals(0, $result['count']);
1828 * Test civicrm_contact_get(,true) with one match.
1830 public function testContactGetOldParamsOneMatch() {
1831 // Insert a row in civicrm_contact creating contact 17
1832 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1833 $op->execute($this->_dbconn
,
1834 $this->createXMLDataSet(dirname(__FILE__
) . '/dataset/contact_17.xml'
1839 'first_name' => 'Test',
1841 $result = $this->callAPISuccess('contact', 'get', $params);
1842 $this->assertEquals(17, $result['values'][17]['contact_id']);
1843 $this->assertEquals(17, $result['id']);
1847 * Test civicrm_contact_search_count().
1849 public function testContactGetEmail() {
1851 'email' => 'man2@yahoo.com',
1852 'contact_type' => 'Individual',
1853 'location_type_id' => 1,
1856 $contact = $this->callAPISuccess('contact', 'create', $params);
1859 'email' => 'man2@yahoo.com',
1861 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
);
1862 $this->assertEquals('man2@yahoo.com', $result['values'][$result['id']]['email']);
1864 $this->callAPISuccess('contact', 'delete', $contact);
1868 * Ensure consistent return format for option group fields.
1870 public function testSetPreferredCommunicationNull() {
1871 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
1872 'preferred_communication_method' => array('Phone', 'SMS'),
1874 $preferredCommunicationMethod = $this->callAPISuccessGetValue('Contact', array(
1875 'id' => $contact['id'],
1876 'return' => 'preferred_communication_method',
1878 $this->assertNotEmpty($preferredCommunicationMethod);
1879 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
1880 'preferred_communication_method' => 'null',
1881 'id' => $contact['id'],
1883 $preferredCommunicationMethod = $this->callAPISuccessGetValue('Contact', array(
1884 'id' => $contact['id'],
1885 'return' => 'preferred_communication_method',
1887 $this->assertEmpty($preferredCommunicationMethod);
1891 * Ensure consistent return format for option group fields.
1893 public function testPseudoFields() {
1895 'preferred_communication_method' => array('Phone', 'SMS'),
1896 'preferred_language' => 'en_US',
1897 'gender_id' => 'Female',
1898 'prefix_id' => 'Mrs.',
1899 'suffix_id' => 'II',
1900 'communication_style_id' => 'Formal',
1903 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, $params));
1905 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
1906 $this->assertEquals('Both', $result['preferred_mail_format']);
1908 $this->assertEquals('en_US', $result['preferred_language']);
1909 $this->assertEquals(1, $result['communication_style_id']);
1910 $this->assertEquals(1, $result['gender_id']);
1911 $this->assertEquals('Female', $result['gender']);
1912 $this->assertEquals('Mrs.', $result['individual_prefix']);
1913 $this->assertEquals(1, $result['prefix_id']);
1914 $this->assertEquals('II', $result['individual_suffix']);
1915 $this->assertEquals(CRM_Core_PseudoConstant
::getKey("CRM_Contact_BAO_Contact", 'suffix_id', 'II'), $result['suffix_id']);
1916 $this->callAPISuccess('contact', 'delete', $contact);
1917 $this->assertEquals(array(
1918 CRM_Core_PseudoConstant
::getKey("CRM_Contact_BAO_Contact", 'preferred_communication_method', 'Phone'),
1919 CRM_Core_PseudoConstant
::getKey("CRM_Contact_BAO_Contact", 'preferred_communication_method', 'SMS'),
1920 ), $result['preferred_communication_method']);
1925 * Test birth date parameters.
1927 * These include value, array & birth_date_high, birth_date_low
1930 public function testContactGetBirthDate() {
1931 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 2 years')));
1932 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 5 years')));
1933 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month -20 years')));
1935 $result = $this->callAPISuccess('contact', 'get', array());
1936 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1937 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1938 $this->assertEquals(1, $result['count']);
1939 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1940 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1941 $this->assertEquals(1, $result['count']);
1942 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1943 $result = $this->callAPISuccess('contact', 'get', array(
1944 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
1945 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
1947 $this->assertEquals(1, $result['count']);
1948 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1949 $result = $this->callAPISuccess('contact', 'get', array(
1950 'birth_date_low' => '-6 years',
1951 'birth_date_high' => '- 3 years',
1953 $this->assertEquals(1, $result['count']);
1954 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1958 * Test Address parameters
1960 * This include state_province, state_province_name, country
1962 public function testContactGetWithAddressFields() {
1963 $individuals = array(
1965 'first_name' => 'abc1',
1966 'contact_type' => 'Individual',
1967 'last_name' => 'xyz1',
1968 'api.address.create' => array(
1969 'country' => 'United States',
1970 'state_province_id' => 'Michigan',
1971 'location_type_id' => 1,
1975 'first_name' => 'abc2',
1976 'contact_type' => 'Individual',
1977 'last_name' => 'xyz2',
1978 'api.address.create' => array(
1979 'country' => 'United States',
1980 'state_province_id' => 'Alabama',
1981 'location_type_id' => 1,
1985 foreach ($individuals as $params) {
1986 $contact = $this->callAPISuccess('contact', 'create', $params);
1989 // Check whether Contact get API return successfully with below Address params.
1990 $fieldsToTest = array(
1991 'state_province_name' => 'Michigan',
1992 'state_province' => 'Michigan',
1993 'country' => 'United States',
1994 'state_province_name' => array('IN' => array('Michigan', 'Alabama')),
1995 'state_province' => array('IN' => array('Michigan', 'Alabama')),
1997 foreach ($fieldsToTest as $field => $value) {
1999 'id' => $contact['id'],
2002 $result = $this->callAPISuccess('Contact', 'get', $getParams);
2003 $this->assertEquals(1, $result['count']);
2008 * Test Deceased date parameters.
2010 * These include value, array & Deceased_date_high, Deceased date_low
2013 public function testContactGetDeceasedDate() {
2014 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 2 years')));
2015 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 5 years')));
2016 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month -20 years')));
2018 $result = $this->callAPISuccess('contact', 'get', array());
2019 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
2020 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
2021 $this->assertEquals(1, $result['count']);
2022 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
2023 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
2024 $this->assertEquals(1, $result['count']);
2025 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
2026 $result = $this->callAPISuccess('contact', 'get', array(
2027 'deceased_date_low' => '-6 years',
2028 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
2030 $this->assertEquals(1, $result['count']);
2031 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
2035 * Test for Contact.get id=@user:username.
2037 public function testContactGetByUsername() {
2038 // Setup - create contact with a uf-match.
2039 $cid = $this->individualCreate(array(
2040 'contact_type' => 'Individual',
2041 'first_name' => 'testGetByUsername',
2042 'last_name' => 'testGetByUsername',
2045 $ufMatchParams = array(
2046 'domain_id' => CRM_Core_Config
::domainID(),
2048 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
2049 'contact_id' => $cid,
2051 $ufMatch = CRM_Core_BAO_UFMatch
::create($ufMatchParams);
2052 $this->assertTrue(is_numeric($ufMatch->id
));
2054 // setup - mock the calls to CRM_Utils_System_*::getUfId
2055 $mockFunction = $this->mockMethod
;
2056 $userSystem = $this->$mockFunction('CRM_Utils_System_UnitTests', array('getUfId'));
2057 $userSystem->expects($this->once())
2059 ->with($this->equalTo('exampleUser'))
2060 ->will($this->returnValue(99));
2061 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
2064 $result = $this->callAPISuccess('Contact', 'get', array(
2065 'id' => '@user:exampleUser',
2067 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
2071 * Test to check return works OK.
2073 public function testContactGetReturnValues() {
2074 $extraParams = array(
2075 'nick_name' => 'Bob',
2077 'email' => 'e@mail.com',
2079 $contactID = $this->individualCreate($extraParams);
2080 //actually it turns out the above doesn't create a phone
2081 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
2082 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
2083 foreach ($extraParams as $key => $value) {
2084 $this->assertEquals($result[$key], $value);
2086 //now we check they are still returned with 'return' key
2087 $result = $this->callAPISuccess('contact', 'getsingle', array(
2089 'return' => array_keys($extraParams),
2091 foreach ($extraParams as $key => $value) {
2092 $this->assertEquals($result[$key], $value);
2097 * Test creating multiple phones using chaining.
2099 * @throws \Exception
2101 public function testCRM13252MultipleChainedPhones() {
2102 $contactID = $this->householdCreate();
2103 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
2105 'contact_id' => $contactID,
2106 'household_name' => 'Household 1',
2107 'contact_type' => 'Household',
2108 'api.phone.create' => array(
2110 'phone' => '111-111-1111',
2111 'location_type_id' => 1,
2112 'phone_type_id' => 1,
2115 'phone' => '222-222-2222',
2116 'location_type_id' => 1,
2117 'phone_type_id' => 2,
2121 $this->callAPISuccess('contact', 'create', $params);
2122 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
2127 * Test for Contact.get id=@user:username (with an invalid username).
2129 public function testContactGetByUnknownUsername() {
2130 // setup - mock the calls to CRM_Utils_System_*::getUfId
2131 $mockFunction = $this->mockMethod
;
2132 $userSystem = $this->$mockFunction('CRM_Utils_System_UnitTests', array('getUfId'));
2133 $userSystem->expects($this->once())
2135 ->with($this->equalTo('exampleUser'))
2136 ->will($this->returnValue(NULL));
2137 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
2140 $result = $this->callAPIFailure('Contact', 'get', array(
2141 'id' => '@user:exampleUser',
2143 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
2147 * Verify attempt to create individual with chained arrays and sequential.
2149 public function testGetIndividualWithChainedArraysAndSequential() {
2150 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
2151 $params['custom_' . $ids['custom_field_id']] = "custom string";
2153 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2156 'first_name' => 'abc3',
2157 'last_name' => 'xyz3',
2158 'contact_type' => 'Individual',
2159 'email' => 'man3@yahoo.com',
2160 'api.website.create' => array(
2162 'url' => "http://civicrm.org",
2165 'url' => "https://civicrm.org",
2170 $result = $this->callAPISuccess('Contact', 'create', $params);
2172 // delete the contact and custom groups
2173 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
2174 $this->customGroupDelete($ids['custom_group_id']);
2175 $this->customGroupDelete($moreIDs['custom_group_id']);
2177 $this->assertEquals($result['id'], $result['values'][0]['id']);
2178 $this->assertArrayKeyExists('api.website.create', $result['values'][0]);
2182 * Verify attempt to create individual with chained arrays.
2184 public function testGetIndividualWithChainedArrays() {
2185 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
2186 $params['custom_' . $ids['custom_field_id']] = "custom string";
2188 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2189 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
2190 $subfile = "APIChainedArray";
2192 'first_name' => 'abc3',
2193 'last_name' => 'xyz3',
2194 'contact_type' => 'Individual',
2195 'email' => 'man3@yahoo.com',
2196 'api.contribution.create' => array(
2197 'receive_date' => '2010-01-01',
2198 'total_amount' => 100.00,
2199 'financial_type_id' => 1,
2200 'payment_instrument_id' => 1,
2201 'non_deductible_amount' => 10.00,
2202 'fee_amount' => 50.00,
2203 'net_amount' => 90.00,
2205 'invoice_id' => 67890,
2207 'contribution_status_id' => 1,
2209 'api.contribution.create.1' => array(
2210 'receive_date' => '2011-01-01',
2211 'total_amount' => 120.00,
2212 'financial_type_id' => $this->_financialTypeId
= 1,
2213 'payment_instrument_id' => 1,
2214 'non_deductible_amount' => 10.00,
2215 'fee_amount' => 50.00,
2216 'net_amount' => 90.00,
2218 'invoice_id' => 67830,
2220 'contribution_status_id' => 1,
2222 'api.website.create' => array(
2224 'url' => "http://civicrm.org",
2229 $result = $this->callAPISuccess('Contact', 'create', $params);
2231 'id' => $result['id'],
2232 'api.website.get' => array(),
2233 'api.Contribution.get' => array(
2234 'total_amount' => '120.00',
2236 'api.CustomValue.get' => 1,
2237 'api.Note.get' => 1,
2239 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2240 // delete the contact
2241 $this->callAPISuccess('contact', 'delete', $result);
2242 $this->customGroupDelete($ids['custom_group_id']);
2243 $this->customGroupDelete($moreIDs['custom_group_id']);
2244 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
2245 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
2249 * Verify attempt to create individual with chained arrays and sequential.
2251 * See https://issues.civicrm.org/jira/browse/CRM-15815
2253 public function testCreateIndividualWithChainedArrayAndSequential() {
2256 'first_name' => 'abc5',
2257 'last_name' => 'xyz5',
2258 'contact_type' => 'Individual',
2259 'email' => 'woman5@yahoo.com',
2260 'api.phone.create' => array(
2261 array('phone' => '03-231 07 95'),
2262 array('phone' => '03-232 51 62'),
2264 'api.website.create' => array(
2265 'url' => 'http://civicrm.org',
2268 $result = $this->callAPISuccess('Contact', 'create', $params);
2270 // I could try to parse the result to see whether the two phone numbers
2271 // and the website are there, but I am not sure about the correct format.
2272 // So I will just fetch it again before checking.
2273 // See also http://forum.civicrm.org/index.php/topic,35393.0.html
2276 'id' => $result['id'],
2277 'api.website.get' => array(),
2278 'api.phone.get' => array(),
2280 $result = $this->callAPISuccess('Contact', 'get', $params);
2282 // delete the contact
2283 $this->callAPISuccess('contact', 'delete', $result);
2285 $this->assertEquals(2, $result['values'][0]['api.phone.get']['count']);
2286 $this->assertEquals(1, $result['values'][0]['api.website.get']['count']);
2290 * Test retrieving an individual with chained array syntax.
2292 public function testGetIndividualWithChainedArraysFormats() {
2293 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
2294 $subfile = "APIChainedArrayFormats";
2295 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
2296 $params['custom_' . $ids['custom_field_id']] = "custom string";
2298 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2300 'first_name' => 'abc3',
2301 'last_name' => 'xyz3',
2302 'contact_type' => 'Individual',
2303 'email' => 'man3@yahoo.com',
2304 'api.contribution.create' => array(
2305 'receive_date' => '2010-01-01',
2306 'total_amount' => 100.00,
2307 'financial_type_id' => $this->_financialTypeId
,
2308 'payment_instrument_id' => 1,
2309 'non_deductible_amount' => 10.00,
2310 'fee_amount' => 50.00,
2311 'net_amount' => 90.00,
2313 'contribution_status_id' => 1,
2314 'skipCleanMoney' => 1,
2316 'api.contribution.create.1' => array(
2317 'receive_date' => '2011-01-01',
2318 'total_amount' => 120.00,
2319 'financial_type_id' => $this->_financialTypeId
,
2320 'payment_instrument_id' => 1,
2321 'non_deductible_amount' => 10.00,
2322 'fee_amount' => 50.00,
2323 'net_amount' => 90.00,
2325 'contribution_status_id' => 1,
2326 'skipCleanMoney' => 1,
2328 'api.website.create' => array(
2330 'url' => "http://civicrm.org",
2335 $result = $this->callAPISuccess('Contact', 'create', $params);
2337 'id' => $result['id'],
2338 'api.website.getValue' => array('return' => 'url'),
2339 'api.Contribution.getCount' => array(),
2340 'api.CustomValue.get' => 1,
2341 'api.Note.get' => 1,
2342 'api.Membership.getCount' => array(),
2344 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2345 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
2346 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
2347 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
2349 $this->callAPISuccess('contact', 'delete', $result);
2350 $this->customGroupDelete($ids['custom_group_id']);
2351 $this->customGroupDelete($moreIDs['custom_group_id']);
2355 * Test complex chaining.
2357 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
2358 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
2359 $params['custom_' . $ids['custom_field_id']] = "custom string";
2360 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2361 $andMoreIDs = $this->CustomGroupMultipleCreateWithFields(array(
2362 'title' => "another group",
2363 'name' => 'another name',
2365 $description = "This demonstrates the usage of chained api functions with multiple custom fields.";
2366 $subfile = "APIChainedArrayMultipleCustom";
2368 'first_name' => 'abc3',
2369 'last_name' => 'xyz3',
2370 'contact_type' => 'Individual',
2371 'email' => 'man3@yahoo.com',
2372 'api.contribution.create' => array(
2373 'receive_date' => '2010-01-01',
2374 'total_amount' => 100.00,
2375 'financial_type_id' => 1,
2376 'payment_instrument_id' => 1,
2377 'non_deductible_amount' => 10.00,
2378 'fee_amount' => 50.00,
2379 'net_amount' => 90.00,
2381 'invoice_id' => 67890,
2383 'contribution_status_id' => 1,
2384 'skipCleanMoney' => 1,
2386 'api.contribution.create.1' => array(
2387 'receive_date' => '2011-01-01',
2388 'total_amount' => 120.00,
2389 'financial_type_id' => 1,
2390 'payment_instrument_id' => 1,
2391 'non_deductible_amount' => 10.00,
2392 'fee_amount' => 50.00,
2393 'net_amount' => 90.00,
2395 'invoice_id' => 67830,
2397 'contribution_status_id' => 1,
2398 'skipCleanMoney' => 1,
2400 'api.website.create' => array(
2402 'url' => "http://civicrm.org",
2405 'custom_' . $ids['custom_field_id'] => "value 1",
2406 'custom_' . $moreIDs['custom_field_id'][0] => "value 2",
2407 'custom_' . $moreIDs['custom_field_id'][1] => "warm beer",
2408 'custom_' . $andMoreIDs['custom_field_id'][1] => "vegemite",
2411 $result = $this->callAPISuccess('Contact', 'create', $params);
2412 $result = $this->callAPISuccess('Contact', 'create', array(
2413 'contact_type' => 'Individual',
2414 'id' => $result['id'],
2416 $moreIDs['custom_field_id'][0] => "value 3",
2418 $ids['custom_field_id'] => "value 4",
2422 'id' => $result['id'],
2423 'api.website.getValue' => array('return' => 'url'),
2424 'api.Contribution.getCount' => array(),
2425 'api.CustomValue.get' => 1,
2427 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2429 $this->customGroupDelete($ids['custom_group_id']);
2430 $this->customGroupDelete($moreIDs['custom_group_id']);
2431 $this->customGroupDelete($andMoreIDs['custom_group_id']);
2432 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
2433 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
2437 * Test checks usage of $values to pick & choose inputs.
2439 public function testChainingValuesCreate() {
2440 $description = "This demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
2441 2 child functions - one receives values from the parent (Contact) and the other child (Tag).";
2442 $subfile = "APIChainedArrayValuesFromSiblingFunction";
2444 'display_name' => 'batman',
2445 'contact_type' => 'Individual',
2446 'api.tag.create' => array(
2447 'name' => '$value.id',
2448 'description' => '$value.display_name',
2449 'format.only_id' => 1,
2451 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
2453 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2454 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
2456 $tablesToTruncate = array(
2459 'civicrm_entity_tag',
2462 $this->quickCleanup($tablesToTruncate, TRUE);
2466 * Test TrueFalse format - I couldn't come up with an easy way to get an error on Get.
2468 public function testContactGetFormatIsSuccessTrue() {
2469 $this->createContactFromXML();
2470 $description = "This demonstrates use of the 'format.is_success' param.
2471 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2472 $subfile = "FormatIsSuccess_True";
2473 $params = array('id' => 17, 'format.is_success' => 1);
2474 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2475 $this->assertEquals(1, $result);
2476 $this->callAPISuccess('Contact', 'Delete', $params);
2480 * Test TrueFalse format.
2482 public function testContactCreateFormatIsSuccessFalse() {
2484 $description = "This demonstrates use of the 'format.is_success' param.
2485 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2486 $subfile = "FormatIsSuccess_Fail";
2487 $params = array('id' => 500, 'format.is_success' => 1);
2488 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2489 $this->assertEquals(0, $result);
2493 * Test long display names.
2497 public function testContactCreateLongDisplayName() {
2498 $result = $this->callAPISuccess('Contact', 'Create', array(
2499 'first_name' => str_pad('a', 64, 'a'),
2500 'last_name' => str_pad('a', 64, 'a'),
2501 'contact_type' => 'Individual',
2503 $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $result['values'][$result['id']]['display_name']);
2504 $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $result['values'][$result['id']]['sort_name']);
2508 * Test Single Entity format.
2510 public function testContactGetSingleEntityArray() {
2511 $this->createContactFromXML();
2512 $description = "This demonstrates use of the 'format.single_entity_array' param.
2513 This param causes the only contact to be returned as an array without the other levels.
2514 It will be ignored if there is not exactly 1 result";
2515 $subfile = "GetSingleContact";
2516 $params = array('id' => 17);
2517 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2518 $this->assertEquals('Test Contact', $result['display_name']);
2519 $this->callAPISuccess('Contact', 'Delete', $params);
2523 * Test Single Entity format.
2525 public function testContactGetFormatCountOnly() {
2526 $this->createContactFromXML();
2527 $description = "This demonstrates use of the 'getCount' action.
2528 This param causes the count of the only function to be returned as an integer.";
2529 $params = array('id' => 17);
2530 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__
, __FILE__
, $description,
2532 $this->assertEquals('1', $result);
2533 $this->callAPISuccess('Contact', 'Delete', $params);
2537 * Test id only format.
2539 public function testContactGetFormatIDOnly() {
2540 $this->createContactFromXML();
2541 $description = "This demonstrates use of the 'format.id_only' param.
2542 This param causes the id of the only entity to be returned as an integer.
2543 It will be ignored if there is not exactly 1 result";
2544 $subfile = "FormatOnlyID";
2545 $params = array('id' => 17, 'format.only_id' => 1);
2546 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2547 $this->assertEquals('17', $result);
2548 $this->callAPISuccess('Contact', 'Delete', $params);
2552 * Test id only format.
2554 public function testContactGetFormatSingleValue() {
2555 $this->createContactFromXML();
2556 $description = "This demonstrates use of the 'format.single_value' param.
2557 This param causes only a single value of the only entity to be returned as an string.
2558 It will be ignored if there is not exactly 1 result";
2559 $subFile = "FormatSingleValue";
2560 $params = array('id' => 17, 'return' => 'display_name');
2561 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
2562 $this->assertEquals('Test Contact', $result);
2563 $this->callAPISuccess('Contact', 'Delete', $params);
2567 * Test that permissions are respected when creating contacts.
2569 public function testContactCreationPermissions() {
2571 'contact_type' => 'Individual',
2572 'first_name' => 'Foo',
2573 'last_name' => 'Bear',
2574 'check_permissions' => TRUE,
2576 $config = CRM_Core_Config
::singleton();
2577 $config->userPermissionClass
->permissions
= array('access CiviCRM');
2578 $result = $this->callAPIFailure('contact', 'create', $params);
2579 $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');
2581 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'add contacts', 'import contacts');
2582 $this->callAPISuccess('contact', 'create', $params);
2586 * Test that delete with skip undelete respects permissions.
2588 public function testContactDeletePermissions() {
2589 $contactID = $this->individualCreate();
2590 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
2591 $this->callAPIFailure('Contact', 'delete', array(
2593 'check_permissions' => 1,
2594 'skip_undelete' => 1,
2596 $this->callAPISuccess('Contact', 'delete', array(
2598 'check_permissions' => 0,
2599 'skip_undelete' => 1,
2604 * Test update with check permissions set.
2606 public function testContactUpdatePermissions() {
2608 'contact_type' => 'Individual',
2609 'first_name' => 'Foo',
2610 'last_name' => 'Bear',
2611 'check_permissions' => TRUE,
2613 $result = $this->callAPISuccess('contact', 'create', $params);
2614 $config = CRM_Core_Config
::singleton();
2616 'id' => $result['id'],
2617 'contact_type' => 'Individual',
2618 'last_name' => 'Bar',
2619 'check_permissions' => TRUE,
2622 $config->userPermissionClass
->permissions
= array('access CiviCRM');
2623 $result = $this->callAPIFailure('contact', 'update', $params);
2624 $this->assertEquals('Permission denied to modify contact record', $result['error_message']);
2626 $config->userPermissionClass
->permissions
= array(
2629 'view all contacts',
2630 'edit all contacts',
2633 $this->callAPISuccess('contact', 'update', $params);
2637 * Set up helper to create a contact.
2639 public function createContactFromXML() {
2640 // Insert a row in civicrm_contact creating contact 17.
2641 $op = new PHPUnit_Extensions_Database_Operation_Insert();
2642 $op->execute($this->_dbconn
,
2643 $this->createXMLDataSet(
2644 dirname(__FILE__
) . '/dataset/contact_17.xml'
2650 * Test contact proximity api.
2652 public function testContactProximity() {
2653 // first create a contact with a SF location with a specific
2655 $contactID = $this->organizationCreate();
2657 // now create the address
2659 'street_address' => '123 Main Street',
2660 'city' => 'San Francisco',
2662 'country_id' => 1228,
2663 'state_province_id' => 1004,
2664 'geo_code_1' => '37.79',
2665 'geo_code_2' => '-122.40',
2666 'location_type_id' => 1,
2667 'contact_id' => $contactID,
2670 $result = $this->callAPISuccess('address', 'create', $params);
2671 $this->assertEquals(1, $result['count']);
2673 // now do a proximity search with a close enough geocode and hope to match
2674 // that specific contact only!
2675 $proxParams = array(
2677 'longitude' => -122.3,
2681 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
2682 $this->assertEquals(1, $result['count']);
2686 * Test that Ajax API permission is sufficient to access getquick api.
2688 * (note that getquick api is required for autocomplete & has ACL permissions applied)
2690 public function testGetquickPermissionCRM13744() {
2691 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviEvent');
2692 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2693 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
2694 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2695 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access AJAX API');
2696 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2700 * Test that getquick returns contacts with an exact first name match first.
2702 * The search string 'b' & 'bob' both return ordered by sort_name if includeOrderByClause
2703 * is true (default) but if it is false then matches are returned in ID order.
2705 * @dataProvider getSearchSortOptions
2707 public function testGetQuickExactFirst($searchParameters, $settings, $firstContact, $secondContact = NULL) {
2708 $this->getQuickSearchSampleData();
2709 $this->callAPISuccess('Setting', 'create', $settings);
2710 $result = $this->callAPISuccess('contact', 'getquick', $searchParameters);
2711 $this->assertEquals($firstContact, $result['values'][0]['sort_name']);
2712 $this->assertEquals($secondContact, $result['values'][1]['sort_name']);
2713 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE));
2716 public function getSearchSortOptions() {
2717 $firstAlphabeticalContactBySortName = 'A Bobby, Bobby';
2718 $secondAlphabeticalContactBySortName = 'Aadvark, Bob';
2719 $secondAlphabeticalContactWithEmailBySortName = 'Bob, Bob';
2720 $firstAlphabeticalContactFirstNameBob = 'Aadvark, Bob';
2721 $secondAlphabeticalContactFirstNameBob = 'Bob, Bob';
2722 $firstByIDContactFirstNameBob = 'Bob, Bob';
2723 $secondByIDContactFirstNameBob = 'K Bobby, Bob';
2724 $firstContactByID = 'Bob, Bob';
2725 $secondContactByID = 'E Bobby, Bobby';
2726 $bobLikeEmail = 'A Bobby, Bobby';
2729 'empty_search_basic' => array(
2730 'search_parameters' => array('name' => '%'),
2731 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2732 'first_contact' => $firstAlphabeticalContactBySortName,
2733 'second_contact' => $secondAlphabeticalContactBySortName,
2735 'empty_search_basic_no_wildcard' => array(
2736 'search_parameters' => array('name' => '%'),
2737 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2738 'first_contact' => $firstAlphabeticalContactBySortName,
2739 'second_contact' => $secondAlphabeticalContactBySortName,
2741 'single_letter_search_basic' => array(
2742 'search_parameters' => array('name' => 'b'),
2743 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2744 'first_contact' => $firstAlphabeticalContactBySortName,
2745 'second_contact' => $secondAlphabeticalContactBySortName,
2747 'bob_search_basic' => array(
2748 'search_parameters' => array('name' => 'bob'),
2749 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2750 'first_contact' => $firstAlphabeticalContactBySortName,
2751 'second_contact' => $secondAlphabeticalContactBySortName,
2753 // This test has been disabled as is proving to be problematic to reproduce due to MySQL sorting issues between different versions
2754 // 'bob_search_no_orderby' => array(
2755 // 'search_parameters' => array('name' => 'bob'),
2756 // 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => FALSE),
2757 // 'first_contact' => $firstContactByID,
2758 // 'second_contact' => $secondContactByID,
2760 'bob_search_no_wildcard' => array(
2761 'search_parameters' => array('name' => 'bob'),
2762 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2763 'second_contact' => $bobLikeEmail,
2764 'first_contact' => $secondAlphabeticalContactFirstNameBob,
2766 // This should be the same as just no wildcard as if we had an exactMatch while searching by
2767 // sort name it would rise to the top CRM-19547
2768 'bob_search_no_wildcard_no_orderby' => array(
2769 'search_parameters' => array('name' => 'bob'),
2770 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2771 'second_contact' => $bobLikeEmail,
2772 'first_contact' => $secondAlphabeticalContactFirstNameBob,
2774 'first_name_search_basic' => array(
2775 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2776 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2777 'first_contact' => $firstAlphabeticalContactFirstNameBob,
2778 'second_contact' => $secondAlphabeticalContactFirstNameBob,
2780 'first_name_search_no_wildcard' => array(
2781 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2782 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2783 'first_contact' => $firstAlphabeticalContactFirstNameBob,
2784 'second_contact' => $secondAlphabeticalContactFirstNameBob,
2786 // This test has been disabled as is proving to be problematic to reproduce due to MySQL sorting issues between different versions
2787 //'first_name_search_no_orderby' => array(
2788 // 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2789 // 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => FALSE),
2790 // 'first_contact' => $firstByIDContactFirstNameBob,
2791 // 'second_contact' => $secondByIDContactFirstNameBob,
2793 'email_search_basic' => array(
2794 'search_parameters' => array('name' => 'bob', 'field_name' => 'email', 'table_name' => 'eml'),
2795 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2796 'first_contact' => $firstAlphabeticalContactBySortName,
2797 'second_contact' => $secondAlphabeticalContactWithEmailBySortName,
2803 * Test that getquick returns contacts with an exact first name match first.
2805 public function testGetQuickEmail() {
2806 $this->getQuickSearchSampleData();
2807 $loggedInContactID = $this->createLoggedInUser();
2808 $result = $this->callAPISuccess('contact', 'getquick', array(
2811 $expectedData = array(
2812 'A Bobby, Bobby :: bob@bobby.com',
2813 'Bob, Bob :: bob@bob.com',
2815 'H Bobby, Bobby :: bob@h.com',
2817 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
2819 $this->assertEquals(6, $result['count']);
2820 foreach ($expectedData as $index => $value) {
2821 $this->assertEquals($value, $result['values'][$index]['data']);
2823 $result = $this->callAPISuccess('contact', 'getquick', array(
2826 $expectedData = array(
2827 'H Bobby, Bobby :: bob@h.com',
2829 foreach ($expectedData as $index => $value) {
2830 $this->assertEquals($value, $result['values'][$index]['data']);
2832 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => FALSE));
2833 $result = $this->callAPISuccess('contact', 'getquick', array(
2836 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE));
2837 $this->assertEquals(0, $result['count']);
2841 * Test that getquick returns contacts with an exact first name match first.
2843 public function testGetQuickEmailACL() {
2844 $this->getQuickSearchSampleData();
2845 $loggedInContactID = $this->createLoggedInUser();
2846 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array();
2847 $result = $this->callAPISuccess('contact', 'getquick', array(
2850 $this->assertEquals(0, $result['count']);
2852 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
2853 CRM_Contact_BAO_Contact_Permission
::cache($loggedInContactID, CRM_Core_Permission
::VIEW
, TRUE);
2854 $result = $this->callAPISuccess('contact', 'getquick', array(
2858 // Without the acl it would be 6 like the previous email getquick test.
2859 $this->assertEquals(5, $result['count']);
2860 $expectedData = array(
2861 'A Bobby, Bobby :: bob@bobby.com',
2862 'Bob, Bob :: bob@bob.com',
2865 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
2867 foreach ($expectedData as $index => $value) {
2868 $this->assertEquals($value, $result['values'][$index]['data']);
2873 * Test that getquick returns contacts with an exact first name match first.
2875 public function testGetQuickExternalID() {
2876 $this->getQuickSearchSampleData();
2877 $result = $this->callAPISuccess('contact', 'getquick', array(
2879 'field_name' => 'external_identifier',
2880 'table_name' => 'cc',
2882 $this->assertEquals(0, $result['count']);
2883 $result = $this->callAPISuccess('contact', 'getquick', array(
2885 'field_name' => 'external_identifier',
2886 'table_name' => 'cc',
2888 $this->assertEquals(1, $result['count']);
2889 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2893 * Test that getquick returns contacts with an exact first name match first.
2895 public function testGetQuickID() {
2896 $max = CRM_Core_DAO
::singleValueQuery("SELECT max(id) FROM civicrm_contact");
2897 $this->getQuickSearchSampleData();
2898 $result = $this->callAPISuccess('contact', 'getquick', array(
2900 'field_name' => 'id',
2901 'table_name' => 'cc',
2903 $this->assertEquals(1, $result['count']);
2904 $this->assertEquals('E Bobby, Bobby', $result['values'][0]['sort_name']);
2905 $result = $this->callAPISuccess('contact', 'getquick', array(
2907 'field_name' => 'contact_id',
2908 'table_name' => 'cc',
2910 $this->assertEquals(1, $result['count']);
2911 $this->assertEquals('E Bobby, Bobby', $result['values'][0]['sort_name']);
2915 * Test that getquick returns contacts with an exact first name match first.
2917 * Depending on the setting the sort name sort might click in next or not - test!
2919 public function testGetQuickFirstName() {
2920 $this->getQuickSearchSampleData();
2921 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2922 $result = $this->callAPISuccess('contact', 'getquick', array(
2924 'field_name' => 'first_name',
2925 'table_name' => 'cc',
2934 foreach ($expected as $index => $value) {
2935 $this->assertEquals($value, $result['values'][$index]['sort_name']);
2937 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
2938 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2939 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2940 // This test has been disabled as is proving to be problematic to reproduce due to MySQL sorting issues between different versions
2941 //$this->assertEquals('E Bobby, Bobby', $result['values'][1]['sort_name']);
2945 * Test that getquick applies ACLs.
2947 public function testGetQuickFirstNameACLs() {
2948 $this->getQuickSearchSampleData();
2949 $userID = $this->createLoggedInUser();
2950 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE, 'search_autocomplete_count' => 15));
2951 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array();
2952 $result = $this->callAPISuccess('contact', 'getquick', array(
2954 'field_name' => 'first_name',
2955 'table_name' => 'cc',
2957 $this->assertEquals(0, $result['count']);
2959 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
2960 CRM_Contact_BAO_Contact_Permission
::cache($userID, CRM_Core_Permission
::VIEW
, TRUE);
2961 $result = $this->callAPISuccess('contact', 'getquick', array(
2963 'field_name' => 'first_name',
2964 'table_name' => 'cc',
2966 $this->assertEquals('K Bobby, Bob', $result['values'][2]['sort_name']);
2967 // Without the ACL 9 would be bob@h.com.
2968 $this->assertEquals('I Bobby, Bobby', $result['values'][10]['sort_name']);
2972 * Full results returned.
2973 * @implements CRM_Utils_Hook::aclWhereClause
2975 * @param string $type
2976 * @param array $tables
2977 * @param array $whereTables
2978 * @param int $contactID
2979 * @param string $where
2981 public function aclWhereNoBobH($type, &$tables, &$whereTables, &$contactID, &$where) {
2982 $where = " (email <> 'bob@h.com' OR email IS NULL) ";
2983 $whereTables['civicrm_email'] = "LEFT JOIN civicrm_email e ON contact_a.id = e.contact_id";
2987 * Test that getquick returns contacts with an exact last name match first.
2989 public function testGetQuickLastName() {
2990 $this->getQuickSearchSampleData();
2991 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2992 $result = $this->callAPISuccess('contact', 'getquick', array(
2994 'field_name' => 'last_name',
2995 'table_name' => 'cc',
3003 foreach ($expected as $index => $value) {
3004 $this->assertEquals($value, $result['values'][$index]['sort_name']);
3006 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
3007 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
3008 $this->assertEquals('Bob, Bob :: bob@bob.com', $result['values'][0]['data']);
3012 * Test that getquick returns contacts by city.
3014 public function testGetQuickCity() {
3015 $this->getQuickSearchSampleData();
3016 $result = $this->callAPISuccess('contact', 'getquick', array(
3018 'field_name' => 'city',
3019 'table_name' => 'sts',
3021 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
3022 $result = $this->callAPISuccess('contact', 'getquick', array(
3024 'field_name' => 'city',
3025 'table_name' => 'sts',
3027 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
3028 $this->assertEquals('C Bobby, Bobby :: Whanganui', $result['values'][1]['data']);
3032 * Set up some sample data for testing quicksearch.
3034 public function getQuickSearchSampleData() {
3036 array('first_name' => 'Bob', 'last_name' => 'Bob', 'external_identifier' => 'abc', 'email' => 'bob@bob.com'),
3037 array('first_name' => 'Bobby', 'last_name' => 'E Bobby', 'external_identifier' => 'abcd'),
3039 'first_name' => 'Bobby',
3040 'last_name' => 'B Bobby',
3041 'external_identifier' => 'bcd',
3042 'api.address.create' => array(
3043 'street_address' => 'Sesame Street',
3044 'city' => 'Toronto',
3045 'location_type_id' => 1,
3049 'first_name' => 'Bobby',
3050 'last_name' => 'C Bobby',
3051 'external_identifier' => 'bcde',
3052 'api.address.create' => array(
3053 'street_address' => 'Te huarahi',
3054 'city' => 'Whanganui',
3055 'location_type_id' => 1,
3058 array('first_name' => 'Bobby', 'last_name' => 'D Bobby', 'external_identifier' => 'efg'),
3059 array('first_name' => 'Bobby', 'last_name' => 'A Bobby', 'external_identifier' => 'hij', 'email' => 'bob@bobby.com'),
3060 array('first_name' => 'Bobby', 'last_name' => 'F Bobby', 'external_identifier' => 'klm'),
3061 array('first_name' => 'Bobby', 'last_name' => 'G Bobby', 'external_identifier' => 'nop'),
3062 array('first_name' => 'Bobby', 'last_name' => 'H Bobby', 'external_identifier' => 'qrs', 'email' => 'bob@h.com'),
3063 array('first_name' => 'Bobby', 'last_name' => 'I Bobby'),
3064 array('first_name' => 'Bobby', 'last_name' => 'J Bobby'),
3065 array('first_name' => 'Bob', 'last_name' => 'K Bobby', 'external_identifier' => 'bcdef'),
3066 array('first_name' => 'Bob', 'last_name' => 'Aadvark'),
3068 foreach ($contacts as $type => $contact) {
3069 $contact['contact_type'] = 'Individual';
3070 $this->callAPISuccess('Contact', 'create', $contact);
3075 * Test get ref api - gets a list of references to an entity.
3077 public function testGetReferenceCounts() {
3078 $result = $this->callAPISuccess('Contact', 'create', array(
3079 'first_name' => 'Testily',
3080 'last_name' => 'McHaste',
3081 'contact_type' => 'Individual',
3082 'api.Address.replace' => array(
3083 'values' => array(),
3085 'api.Email.replace' => array(
3088 'email' => 'spam@dev.null',
3090 'location_type_id' => 1,
3094 'api.Phone.replace' => array(
3097 'phone' => '234-567-0001',
3099 'location_type_id' => 1,
3102 'phone' => '234-567-0002',
3104 'location_type_id' => 1,
3110 //$dao = new CRM_Contact_BAO_Contact();
3111 //$dao->id = $result['id'];
3112 //$this->assertTrue((bool) $dao->find(TRUE));
3114 //$refCounts = $dao->getReferenceCounts();
3115 //$this->assertTrue(is_array($refCounts));
3116 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
3118 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
3119 'id' => $result['id'],
3121 $refCountsIdx = CRM_Utils_Array
::index(array('name'), $refCounts['values']);
3123 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
3124 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
3125 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
3126 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
3127 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
3131 * Test the use of sql operators.
3133 public function testSQLOperatorsOnContactAPI() {
3134 $this->individualCreate();
3135 $this->organizationCreate();
3136 $this->householdCreate();
3137 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
3138 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
3139 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
3140 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
3144 * CRM-14743 - test api respects search operators.
3146 public function testGetModifiedDateByOperators() {
3147 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
3148 $contact1 = $this->individualCreate();
3149 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
3150 CRM_Core_DAO
::executeQuery($sql);
3151 $contact2 = $this->individualCreate();
3152 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
3153 CRM_Core_DAO
::executeQuery($sql);
3154 $contact3 = $this->householdCreate();
3155 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
3156 CRM_Core_DAO
::executeQuery($sql);
3157 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
3158 $this->assertEquals($contacts['count'], 3);
3159 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
3160 $this->assertEquals($contacts['count'], $preExistingContactCount);
3164 * CRM-14743 - test api respects search operators.
3166 public function testGetCreatedDateByOperators() {
3167 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
3168 $contact1 = $this->individualCreate();
3169 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
3170 CRM_Core_DAO
::executeQuery($sql);
3171 $contact2 = $this->individualCreate();
3172 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
3173 CRM_Core_DAO
::executeQuery($sql);
3174 $contact3 = $this->householdCreate();
3175 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
3176 CRM_Core_DAO
::executeQuery($sql);
3177 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
3178 $this->assertEquals($contacts['count'], 3);
3179 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
3180 $this->assertEquals($contacts['count'], $preExistingContactCount);
3184 * CRM-14263 check that API is not affected by search profile related bug.
3186 public function testReturnCityProfile() {
3187 $contactID = $this->individualCreate();
3188 CRM_Core_Config
::singleton()->defaultSearchProfileID
= 1;
3189 $this->callAPISuccess('address', 'create', array(
3190 'contact_id' => $contactID,
3191 'city' => 'Cool City',
3192 'location_type_id' => 1,
3194 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
3195 $this->assertEquals(1, $result['count']);
3199 * CRM-15443 - ensure getlist api does not return deleted contacts.
3201 public function testGetlistExcludeConditions() {
3203 $contact = $this->individualCreate(array('last_name' => $name));
3204 $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
3205 $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
3206 // We should get all but the deleted contact.
3207 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
3208 $this->assertEquals(2, $result['count']);
3209 // Force-exclude the deceased contact.
3210 $result = $this->callAPISuccess('contact', 'getlist', array(
3212 'params' => array('is_deceased' => 0),
3214 $this->assertEquals(1, $result['count']);
3215 $this->assertEquals($contact, $result['values'][0]['id']);
3219 * Test contact getactions.
3221 public function testGetActions() {
3222 $description = "Getting the available actions for an entity.";
3223 $result = $this->callAPIAndDocument($this->_entity
, 'getactions', array(), __FUNCTION__
, __FILE__
, $description);
3243 $deprecated = array(
3247 foreach ($expected as $action) {
3248 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
3250 foreach ($deprecated as $action) {
3251 $this->assertArrayKeyExists($action, $result['deprecated']);
3256 * Test the duplicate check function.
3258 public function testDuplicateCheck() {
3260 'first_name' => 'Harry',
3261 'last_name' => 'Potter',
3262 'email' => 'harry@hogwarts.edu',
3263 'contact_type' => 'Individual',
3265 $this->callAPISuccess('Contact', 'create', $harry);
3266 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3270 $this->assertEquals(1, $result['count']);
3271 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3273 'first_name' => 'Harry',
3274 'last_name' => 'Potter',
3275 'email' => 'no5@privet.drive',
3276 'contact_type' => 'Individual',
3279 $this->assertEquals(0, $result['count']);
3280 $this->callAPIFailure('Contact', 'create', array_merge($harry, array('dupe_check' => 1)));
3284 * Test the duplicate check function.
3286 public function testDuplicateCheckRuleNotReserved() {
3288 'first_name' => 'Harry',
3289 'last_name' => 'Potter',
3290 'email' => 'harry@hogwarts.edu',
3291 'contact_type' => 'Individual',
3293 $defaultRule = $this->callAPISuccess('RuleGroup', 'getsingle', array('used' => 'Unsupervised', 'is_reserved' => 1));
3294 $this->callAPISuccess('RuleGroup', 'create', array('id' => $defaultRule['id'], 'is_reserved' => 0));
3295 $this->callAPISuccess('Contact', 'create', $harry);
3296 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3300 $this->assertEquals(1, $result['count']);
3301 $this->callAPISuccess('RuleGroup', 'create', array('id' => $defaultRule['id'], 'is_reserved' => 1));
3305 * Test variants on retrieving contact by type.
3307 public function testGetByContactType() {
3308 $individual = $this->callAPISuccess('Contact', 'create', array(
3309 'email' => 'individual@test.com',
3310 'contact_type' => 'Individual',
3312 $household = $this->callAPISuccess('Contact', 'create', array(
3313 'household_name' => 'household@test.com',
3314 'contact_type' => 'Household',
3316 $organization = $this->callAPISuccess('Contact', 'create', array(
3317 'organization_name' => 'organization@test.com',
3318 'contact_type' => 'Organization',
3320 // Test with id - getsingle will throw an exception if not found
3321 $this->callAPISuccess('Contact', 'getsingle', array(
3322 'id' => $individual['id'],
3323 'contact_type' => 'Individual',
3325 $this->callAPISuccess('Contact', 'getsingle', array(
3326 'id' => $individual['id'],
3327 'contact_type' => array('IN' => array('Individual')),
3330 $this->callAPISuccess('Contact', 'getsingle', array(
3331 'id' => $organization['id'],
3332 'contact_type' => array('IN' => array('Individual', 'Organization')),
3335 $result = $this->callAPISuccess('Contact', 'get', array(
3336 'contact_type' => array('IN' => array('Individual', 'Organization')),
3337 'options' => array('limit' => 0),
3340 $this->assertContains($organization['id'], array_keys($result['values']));
3341 $this->assertContains($individual['id'], array_keys($result['values']));
3342 $this->assertNotContains($household['id'], array_keys($result['values']));
3344 $result = $this->callAPISuccess('Contact', 'get', array(
3345 'contact_type' => 'Household',
3346 'options' => array('limit' => 0),
3349 $this->assertNotContains($organization['id'], array_keys($result['values']));
3350 $this->assertNotContains($individual['id'], array_keys($result['values']));
3351 $this->assertContains($household['id'], array_keys($result['values']));
3355 * Test merging 2 contacts.
3357 * Someone kindly bequethed us the legacy of mixed up use of main_id & other_id
3358 * in the params for contact.merge api.
3360 * This test protects that legacy.
3362 public function testMergeBizzareOldParams() {
3363 $this->createLoggedInUser();
3364 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3365 $mainContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3366 $this->callAPISuccess('contact', 'merge', array(
3367 'main_id' => $mainContact['id'],
3368 'other_id' => $otherContact['id'],
3370 $contacts = $this->callAPISuccess('contact', 'get', $this->_params
);
3371 $this->assertEquals($otherContact['id'], $contacts['id']);
3375 * Test merging 2 contacts.
3377 public function testMerge() {
3378 $this->createLoggedInUser();
3379 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3380 $retainedContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3381 $this->callAPISuccess('contact', 'merge', array(
3382 'to_keep_id' => $retainedContact['id'],
3383 'to_remove_id' => $otherContact['id'],
3384 'auto_flip' => FALSE,
3387 $contacts = $this->callAPISuccess('contact', 'get', $this->_params
);
3388 $this->assertEquals($retainedContact['id'], $contacts['id']);
3389 $activity = $this->callAPISuccess('Activity', 'getsingle', array(
3390 'target_contact_id' => $retainedContact['id'],
3391 'activity_type_id' => 'Contact Merged',
3393 $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($activity['activity_date_time'])));
3394 $activity2 = $this->callAPISuccess('Activity', 'getsingle', array(
3395 'target_contact_id' => $otherContact['id'],
3396 'activity_type_id' => 'Contact Deleted by Merge',
3398 $this->assertEquals($activity['id'], $activity2['parent_id']);
3399 $this->assertEquals('Normal', civicrm_api3('option_value', 'getvalue', array(
3400 'value' => $activity['priority_id'],
3401 'return' => 'label',
3402 'option_group_id' => 'priority',
3408 * Test retrieving merged contacts.
3410 * The goal here is to start with a contact deleted by merged and find out the contact that is the current version of them.
3412 public function testMergedGet() {
3413 $this->contactIDs
[] = $this->individualCreate();
3414 $this->contactIDs
[] = $this->individualCreate();
3415 $this->contactIDs
[] = $this->individualCreate();
3416 $this->contactIDs
[] = $this->individualCreate();
3418 // First do an 'unnatural merge' - they 'like to merge into the lowest but this will mean that contact 0 merged to contact [3].
3419 // When the batch merge runs.... the new lowest contact is contact[1]. All contacts will merge into that contact,
3420 // including contact[3], resulting in only 3 existing at the end. For each contact the correct answer to 'who did I eventually
3421 // wind up being should be [1]
3422 $this->callAPISuccess('Contact', 'merge', ['to_remove_id' => $this->contactIDs
[0], 'to_keep_id' => $this->contactIDs
[3]]);
3424 $this->callAPISuccess('Job', 'process_batch_merge', []);
3425 foreach ($this->contactIDs
as $contactID) {
3426 if ($contactID === $this->contactIDs
[1]) {
3429 $result = $this->callAPIAndDocument('Contact', 'getmergedto', ['sequential' => 1, 'contact_id' => $contactID], __FUNCTION__
, __FILE__
);
3430 $this->assertEquals(1, $result['count']);
3431 $this->assertEquals($this->contactIDs
[1], $result['values'][0]['id']);
3434 $result = $this->callAPIAndDocument('Contact', 'getmergedfrom', ['contact_id' => $this->contactIDs
[1]], __FUNCTION__
, __FILE__
)['values'];
3435 $mergedContactIds = array_merge(array_diff($this->contactIDs
, [$this->contactIDs
[1]]));
3436 $this->assertEquals($mergedContactIds, array_keys($result));
3440 * Test merging 2 contacts with delete to trash off.
3442 * We are checking that there is no error due to attempting to add an activity for the
3447 public function testMergeNoTrash() {
3448 $this->createLoggedInUser();
3449 $this->callAPISuccess('Setting', 'create', array('contact_undelete' => FALSE));
3450 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3451 $retainedContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3452 $this->callAPISuccess('contact', 'merge', array(
3453 'to_keep_id' => $retainedContact['id'],
3454 'to_remove_id' => $otherContact['id'],
3455 'auto_flip' => FALSE,
3457 $this->callAPISuccess('Setting', 'create', array('contact_undelete' => TRUE));
3461 * Ensure format with return=group shows comma-separated group IDs.
3465 public function testContactGetReturnGroup() {
3466 // Set up a contact, asser that they were created.
3467 $contact_params = array(
3468 'contact_type' => 'Individual',
3469 'first_name' => 'Test',
3470 'last_name' => 'Groupmember',
3471 'email' => 'test@example.org',
3473 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3474 $this->assertEquals(0, $create_contact['is_error']);
3475 $this->assertInternalType('int', $create_contact['id']);
3477 $created_contact_id = $create_contact['id'];
3479 // Set up multiple groups, add the contact to the groups.
3480 $test_groups = array('Test group A', 'Test group B');
3481 foreach ($test_groups as $title) {
3482 // Use this contact as group owner, since we know they exist.
3483 $group_params = array(
3485 'created_id' => $created_contact_id,
3487 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3488 $this->assertEquals(0, $create_group['is_error']);
3489 $this->assertInternalType('int', $create_group['id']);
3491 $created_group_ids[] = $create_group['id'];
3493 // Add contact to the new group.
3494 $group_contact_params = array(
3495 'contact_id' => $created_contact_id,
3496 'group_id' => $create_group['id'],
3498 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3499 $this->assertEquals(0, $create_group_contact['is_error']);
3500 $this->assertInternalType('int', $create_group_contact['added']);
3503 // Use the Contact,get API to retrieve the contact
3504 $contact_get_params = array(
3505 'id' => $created_contact_id,
3506 'return' => 'group',
3508 $contact_get = $this->callApiSuccess('Contact', 'get', $contact_get_params);
3509 $this->assertInternalType('array', $contact_get['values'][$created_contact_id]);
3510 $this->assertInternalType('string', $contact_get['values'][$created_contact_id]['groups']);
3512 // Ensure they are shown as being in each created group.
3513 $contact_group_ids = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3514 foreach ($created_group_ids as $created_group_id) {
3515 $this->assertContains($created_group_id, $contact_group_ids);
3520 * CRM-20144 Verify that passing title of group works as well as id
3521 * Tests the following formats
3522 * contact.get group='title1'
3523 * contact.get group=id1
3525 public function testContactGetWithGroupTitle() {
3526 // Set up a contact, asser that they were created.
3527 $contact_params = array(
3528 'contact_type' => 'Individual',
3529 'first_name' => 'Test2',
3530 'last_name' => 'Groupmember',
3531 'email' => 'test@example.org',
3533 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3534 $created_contact_id = $create_contact['id'];
3535 // Set up multiple groups, add the contact to the groups.
3536 $test_groups = array('Test group C', 'Test group D');
3537 foreach ($test_groups as $title) {
3538 $group_params = array(
3540 'created_id' => $created_contact_id,
3542 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3543 $created_group_id = $create_group['id'];
3545 // Add contact to the new group.
3546 $group_contact_params = array(
3547 'contact_id' => $created_contact_id,
3548 'group_id' => $create_group['id'],
3550 $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3551 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => $title, 'return' => 'group'));
3552 $this->assertEquals(1, $contact_get['count']);
3553 $this->assertEquals($created_contact_id, $contact_get['id']);
3554 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3555 $this->assertContains((string) $create_group['id'], $contact_groups);
3556 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => $created_group_id, 'return' => 'group'));
3557 $this->assertEquals($created_contact_id, $contact_get2['id']);
3558 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3559 $this->assertContains((string) $create_group['id'], $contact_groups2);
3560 $this->callAPISuccess('group', 'delete', array('id' => $created_group_id));
3562 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3566 * CRM-20144 Verify that passing title of group works as well as id
3567 * Tests the following formats
3568 * contact.get group=array('title1', title1)
3569 * contact.get group=array('IN' => array('title1', 'title2)
3571 public function testContactGetWithGroupTitleMultipleGroups() {
3572 $description = "Get all from group and display contacts.";
3573 $subFile = "GroupFilterUsingContactAPI";
3574 // Set up a contact, asser that they were created.
3575 $contact_params = array(
3576 'contact_type' => 'Individual',
3577 'first_name' => 'Test2',
3578 'last_name' => 'Groupmember',
3579 'email' => 'test@example.org',
3581 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3582 $created_contact_id = $create_contact['id'];
3583 $createdGroupsTitles = $createdGroupsIds = array();
3584 // Set up multiple groups, add the contact to the groups.
3585 $test_groups = array('Test group C', 'Test group D');
3586 foreach ($test_groups as $title) {
3587 $group_params = array(
3589 'created_id' => $created_contact_id,
3591 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3592 $created_group_id = $create_group['id'];
3593 $createdGroupsIds[] = $create_group['id'];
3594 $createdGroupTitles[] = $title;
3595 // Add contact to the new group.
3596 $group_contact_params = array(
3597 'contact_id' => $created_contact_id,
3598 'group_id' => $create_group['id'],
3600 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3602 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => $createdGroupTitles, 'return' => 'group'));
3603 $this->assertEquals(1, $contact_get['count']);
3604 $this->assertEquals($created_contact_id, $contact_get['id']);
3605 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3606 foreach ($createdGroupsIds as $id) {
3607 $this->assertContains((string) $id, $contact_groups);
3609 $contact_get2 = $this->callAPIAndDocument('contact', 'get', array('group' => array('IN' => $createdGroupTitles)), __FUNCTION__
, __FILE__
, $description, $subFile);
3610 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => array('IN' => $createdGroupTitles), 'return' => 'group'));
3611 $this->assertEquals($created_contact_id, $contact_get2['id']);
3612 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3613 foreach ($createdGroupsIds as $id) {
3614 $this->assertContains((string) $id, $contact_groups2);
3616 foreach ($createdGroupsIds as $id) {
3617 $this->callAPISuccess('group', 'delete', array('id' => $id));
3619 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3623 * CRM-20144 Verify that passing title of group works as well as id
3624 * Tests the following formats
3625 * contact.get group=array('title1' => 1)
3626 * contact.get group=array('titke1' => 1, 'title2' => 1)
3627 * contact.get group=array('id1' => 1)
3628 * contact.get group=array('id1' => 1, id2 => 1)
3630 public function testContactGetWithGroupTitleMultipleGroupsLegacyFormat() {
3631 // Set up a contact, asser that they were created.
3632 $contact_params = array(
3633 'contact_type' => 'Individual',
3634 'first_name' => 'Test2',
3635 'last_name' => 'Groupmember',
3636 'email' => 'test@example.org',
3638 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3639 $created_contact_id = $create_contact['id'];
3640 $createdGroupsTitles = $createdGroupsIds = array();
3641 // Set up multiple groups, add the contact to the groups.
3642 $test_groups = array('Test group C', 'Test group D');
3643 foreach ($test_groups as $title) {
3644 $group_params = array(
3646 'created_id' => $created_contact_id,
3648 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3649 $created_group_id = $create_group['id'];
3650 $createdGroupsIds[] = $create_group['id'];
3651 $createdGroupTitles[] = $title;
3652 // Add contact to the new group.
3653 $group_contact_params = array(
3654 'contact_id' => $created_contact_id,
3655 'group_id' => $create_group['id'],
3657 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3659 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupTitles[0] => 1), 'return' => 'group'));
3660 $this->assertEquals(1, $contact_get['count']);
3661 $this->assertEquals($created_contact_id, $contact_get['id']);
3662 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3663 foreach ($createdGroupsIds as $id) {
3664 $this->assertContains((string) $id, $contact_groups);
3666 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupTitles[0] => 1, $createdGroupTitles[1] => 1), 'return' => 'group'));
3667 $this->assertEquals(1, $contact_get2['count']);
3668 $this->assertEquals($created_contact_id, $contact_get2['id']);
3669 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3670 foreach ($createdGroupsIds as $id) {
3671 $this->assertContains((string) $id, $contact_groups2);
3673 $contact_get3 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupsIds[0] => 1), 'return' => 'group'));
3674 $this->assertEquals($created_contact_id, $contact_get3['id']);
3675 $contact_groups3 = explode(',', $contact_get3['values'][$created_contact_id]['groups']);
3676 foreach ($createdGroupsIds as $id) {
3677 $this->assertContains((string) $id, $contact_groups3);
3679 $contact_get4 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupsIds[0] => 1, $createdGroupsIds[1] => 1), 'return' => 'group'));
3680 $this->assertEquals($created_contact_id, $contact_get4['id']);
3681 $contact_groups4 = explode(',', $contact_get4['values'][$created_contact_id]['groups']);
3682 foreach ($createdGroupsIds as $id) {
3683 $this->assertContains((string) $id, $contact_groups4);
3685 foreach ($createdGroupsIds as $id) {
3686 $this->callAPISuccess('group', 'delete', array('id' => $id));
3688 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3692 * Test the prox_distance functionality works.
3694 * This is primarily testing functionality in the BAO_Query object that 'happens to be'
3695 * accessible via the api.
3697 public function testContactGetProximity() {
3698 CRM_Core_Config
::singleton()->geocodeMethod
= 'CRM_Utils_MockGeocoder';
3699 $this->individualCreate();
3700 $contactID = $this->individualCreate();
3701 $this->callAPISuccess('Address', 'create', [
3702 'contact_id' => $contactID,
3704 'city' => 'Whangarei',
3705 'street_address' => 'Dent St',
3706 'geo_code_1' => '-35.8743325',
3707 'geo_code_2' => '174.4567136',
3708 'location_type_id' => 'Home',
3710 $contact = $this->callAPISuccess('Contact', 'get', [
3711 'prox_distance' => 100,
3712 'prox_geo_code_1' => '-35.72192',
3713 'prox_geo_code_2' => '174.32034',
3715 $this->assertEquals(1, $contact['count']);
3716 $this->assertEquals($contactID, $contact['id']);
3719 public function testLoggedInUserAPISupportToken() {
3720 $description = "Get contact id of the current logged in user";
3721 $subFile = "ContactIDOfLoggedInUserContactAPI";
3722 $cid = $this->createLoggedInUser();
3723 $contact = $this->callAPIAndDocument('contact', 'get', array('id' => 'user_contact_id'), __FUNCTION__
, __FILE__
, $description, $subFile);
3724 $this->assertEquals($cid, $contact['id']);
3731 protected function putGroupContactCacheInClearableState($groupID, $contact) {
3732 // We need to force the situation where there is invalid data in the cache and it
3733 // is due to be cleared.
3734 CRM_Core_DAO
::executeQuery("
3735 INSERT INTO civicrm_group_contact_cache (group_id, contact_id)
3736 VALUES ({$groupID}, {$contact['id']})
3738 CRM_Core_DAO
::executeQuery("UPDATE civicrm_group SET cache_date = '2017-01-01'");
3739 // Reset so it does not skip.
3740 Civi
::$statics['CRM_Contact_BAO_GroupContactCache']['is_refresh_init'] = FALSE;
3744 * CRM-21041 Test if 'communication style' is set to site default if not passed.
3746 public function testCreateCommunicationStyleUnset() {
3747 $this->callAPISuccess('Contact', 'create', array(
3748 'first_name' => 'John',
3749 'last_name' => 'Doe',
3750 'contact_type' => 'Individual')
3752 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Doe'));
3753 $this->assertEquals(1, $result['communication_style_id']);
3757 * CRM-21041 Test if 'communication style' is set if value is passed.
3759 public function testCreateCommunicationStylePassed() {
3760 $this->callAPISuccess('Contact', 'create', array(
3761 'first_name' => 'John',
3762 'last_name' => 'Doe',
3763 'contact_type' => 'Individual',
3764 'communication_style_id' => 'Familiar',
3766 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Doe'));
3768 'option_group_id' => 'communication_style',
3769 'label' => 'Familiar',
3770 'return' => 'value',
3772 $optionResult = civicrm_api3('OptionValue', 'get', $params);
3773 $communicationStyle = reset($optionResult['values']);
3774 $this->assertEquals($communicationStyle['value'], $result['communication_style_id']);
3778 * Test that creating a contact with various contact greetings works.
3780 public function testContactGreetingsCreate() {
3781 $contact = $this->callAPISuccess('Contact', 'create', array('first_name' => 'Alan', 'last_name' => 'MouseMouse', 'contact_type' => 'Individual'));
3782 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3783 $this->assertEquals('Dear Alan', $contact['postal_greeting_display']);
3785 $contact = $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'postal_greeting_id' => 2));
3786 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3787 $this->assertEquals('Dear Alan MouseMouse', $contact['postal_greeting_display']);
3789 $contact = $this->callAPISuccess('Contact', 'create', array('organization_name' => 'Alan\'s Show', 'contact_type' => 'Organization'));
3790 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting, addressee, email_greeting'));
3791 $this->assertEquals('', $contact['postal_greeting_display']);
3792 $this->assertEquals('', $contact['email_greeting_display']);
3793 $this->assertEquals('Alan\'s Show', $contact['addressee_display']);
3797 * Test that creating a contact with various contact greetings works.
3799 public function testContactGreetingsCreateWithCustomField() {
3800 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
3801 $contact = $this->callAPISuccess('Contact', 'create', array('first_name' => 'Alan', 'contact_type' => 'Individual', 'custom_' . $ids['custom_field_id'] => 'Mice'));
3803 // Change postal greeting to involve a custom field.
3804 $postalOption = $this->callAPISuccessGetSingle('OptionValue', array('option_group_id' => 'postal_greeting', 'filter' => 1, 'is_default' => 1));
3805 $this->callAPISuccess('OptionValue', 'create', array(
3806 'id' => $postalOption['id'],
3807 'name' => 'Dear {contact.first_name} {contact.custom_' . $ids['custom_field_id'] . '}',
3808 'label' => 'Dear {contact.first_name} {contact.custom_' . $ids['custom_field_id'] . '}',
3811 // Update contact & see if postal greeting now reflects the new string.
3812 $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'last_name' => 'MouseyMousey'));
3813 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3814 $this->assertEquals('Dear Alan Mice', $contact['postal_greeting_display']);
3816 // Set contact to have no postal greeting & check it is correct.
3817 $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'postal_greeting_id' => 'null'));
3818 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3819 $this->assertEquals('', $contact['postal_greeting_display']);
3822 $this->callAPISuccess('OptionValue', 'create', array('id' => $postalOption['id'], 'name' => 'Dear {contact.first_name}'));
3823 $this->customFieldDelete($ids['custom_field_id']);
3824 $this->customGroupDelete($ids['custom_group_id']);
3828 * Test getunique api call for Contact entity
3830 public function testContactGetUnique() {
3831 $result = $this->callAPIAndDocument($this->_entity
, 'getunique', array(), __FUNCTION__
, __FILE__
);
3832 $this->assertEquals(1, $result['count']);
3833 $this->assertEquals(array('external_identifier'), $result['values']['UI_external_identifier']);
3836 public function testSmartGroupsForRelatedContacts() {
3837 $rtype1 = $this->callAPISuccess('relationship_type', 'create', array(
3838 "name_a_b" => uniqid() . " Child of",
3839 "name_b_a" => uniqid() . " Parent of",
3841 $rtype2 = $this->callAPISuccess('relationship_type', 'create', array(
3842 "name_a_b" => uniqid() . " Household Member of",
3843 "name_b_a" => uniqid() . " Household Member is",
3845 $h1 = $this->householdCreate();
3846 $c1 = $this->individualCreate(array('last_name' => 'Adams'));
3847 $c2 = $this->individualCreate(array('last_name' => 'Adams'));
3848 $this->callAPISuccess('relationship', 'create', array(
3849 'contact_id_a' => $c1,
3850 'contact_id_b' => $c2,
3852 'relationship_type_id' => $rtype1['id'], // Child of
3854 $this->callAPISuccess('relationship', 'create', array(
3855 'contact_id_a' => $c1,
3856 'contact_id_b' => $h1,
3858 'relationship_type_id' => $rtype2['id'], // Household Member of
3860 $this->callAPISuccess('relationship', 'create', array(
3861 'contact_id_a' => $c2,
3862 'contact_id_b' => $h1,
3864 'relationship_type_id' => $rtype2['id'], // Household Member of
3868 'formValues' => array(
3869 'display_relationship_type' => $rtype1['id'] . '_a_b', // Child of
3870 'sort_name' => 'Adams',
3873 $g1ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid()));
3875 'formValues' => array(
3876 'display_relationship_type' => $rtype2['id'] . '_a_b', // Household Member of
3879 $g2ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid()));
3881 'formValues' => array(
3882 'display_relationship_type' => $rtype2['id'] . '_b_a', // Household Member is
3885 // the reverse of g2 which adds another layer for overlap at related contact filter
3886 $g3ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid()));
3887 CRM_Contact_BAO_GroupContactCache
::loadAll();
3888 $g1Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g1ID));
3889 $g2Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g2ID));
3890 $g3Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g3ID));
3891 $this->assertTrue($g1Contacts['count'] == 1);
3892 $this->assertTrue($g2Contacts['count'] == 2);
3893 $this->assertTrue($g3Contacts['count'] == 1);