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 $contact = $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 old keys still work.
402 * Verify that attempt to create individual contact with
403 * first and last names and old key values works
405 public function testCreateNameIndividualOldKeys() {
407 'individual_prefix' => 'Dr.',
408 'first_name' => 'abc1',
409 'contact_type' => 'Individual',
410 'last_name' => 'xyz1',
411 'individual_suffix' => 'Jr.',
414 $contact = $this->callAPISuccess('contact', 'create', $params);
415 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
417 $this->assertArrayKeyExists('prefix_id', $result);
418 $this->assertArrayKeyExists('suffix_id', $result);
419 $this->assertArrayKeyExists('gender_id', $result);
420 $this->assertEquals(4, $result['prefix_id']);
421 $this->assertEquals(1, $result['suffix_id']);
425 * Test preferred keys work.
427 * Verify that attempt to create individual contact with
428 * first and last names and old key values works
430 public function testCreateNameIndividualRecommendedKeys2() {
432 'prefix_id' => 'Dr.',
433 'first_name' => 'abc1',
434 'contact_type' => 'Individual',
435 'last_name' => 'xyz1',
436 'suffix_id' => 'Jr.',
437 'gender_id' => 'Male',
440 $contact = $this->callAPISuccess('contact', 'create', $params);
441 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
443 $this->assertArrayKeyExists('prefix_id', $result);
444 $this->assertArrayKeyExists('suffix_id', $result);
445 $this->assertArrayKeyExists('gender_id', $result);
446 $this->assertEquals(4, $result['prefix_id']);
447 $this->assertEquals(1, $result['suffix_id']);
451 * Test household name is sufficient for create.
453 * Verify that attempt to create household contact with only
454 * household name succeeds
456 public function testCreateNameHousehold() {
458 'household_name' => 'The abc Household',
459 'contact_type' => 'Household',
461 $this->callAPISuccess('contact', 'create', $params);
465 * Test organization name is sufficient for create.
467 * Verify that attempt to create organization contact with only
468 * organization name succeeds.
470 public function testCreateNameOrganization() {
472 'organization_name' => 'The abc Organization',
473 'contact_type' => 'Organization',
475 $this->callAPISuccess('contact', 'create', $params);
479 * Verify that attempt to create organization contact without organization name fails.
481 public function testCreateNoNameOrganization() {
483 'first_name' => 'The abc Organization',
484 'contact_type' => 'Organization',
486 $this->callAPIFailure('contact', 'create', $params);
490 * Check that permissions on API key are restricted (CRM-18112).
492 public function testCreateApiKey() {
493 $config = CRM_Core_Config
::singleton();
494 $contactId = $this->individualCreate(array(
499 // Allow edit -- because permissions aren't being checked
500 $config->userPermissionClass
->permissions
= array();
501 $result = $this->callAPISuccess('Contact', 'create', array(
503 'api_key' => 'original',
505 $this->assertEquals('original', $result['values'][$contactId]['api_key']);
507 // Allow edit -- because we have adequate permission
508 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'edit all contacts', 'edit api keys');
509 $result = $this->callAPISuccess('Contact', 'create', array(
510 'check_permissions' => 1,
512 'api_key' => 'abcd1234',
514 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
516 // Disallow edit -- because we don't have permission
517 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'edit all contacts');
518 $result = $this->callAPIFailure('Contact', 'create', array(
519 'check_permissions' => 1,
521 'api_key' => 'defg4321',
523 $this->assertRegExp(';Permission denied to modify api key;', $result['error_message']);
525 // Return everything -- because permissions are not being checked
526 $config->userPermissionClass
->permissions
= array();
527 $result = $this->callAPISuccess('Contact', 'create', array(
529 'first_name' => 'A2',
531 $this->assertEquals('A2', $result['values'][$contactId]['first_name']);
532 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
533 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
535 // Return everything -- because we have adequate permission
536 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'edit all contacts', 'edit api keys');
537 $result = $this->callAPISuccess('Contact', 'create', array(
538 'check_permissions' => 1,
540 'first_name' => 'A3',
542 $this->assertEquals('A3', $result['values'][$contactId]['first_name']);
543 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
544 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
546 // Restricted return -- because we don't have permission
547 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'edit all contacts');
548 $result = $this->callAPISuccess('Contact', 'create', array(
549 'check_permissions' => 1,
551 'first_name' => 'A4',
553 $this->assertEquals('A4', $result['values'][$contactId]['first_name']);
554 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
555 $this->assertTrue(empty($result['values'][$contactId]['api_key']));
559 * Check with complete array + custom field.
561 * Note that the test is written on purpose without any
562 * variables specific to participant so it can be replicated into other entities
563 * and / or moved to the automated test suite
565 public function testCreateWithCustom() {
566 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
568 $params = $this->_params
;
569 $params['custom_' . $ids['custom_field_id']] = "custom string";
570 $description = "This demonstrates setting a custom field through the API.";
571 $result = $this->callAPIAndDocument($this->_entity
, 'create', $params, __FUNCTION__
, __FILE__
, $description);
573 $check = $this->callAPISuccess($this->_entity
, 'get', array(
574 'return.custom_' . $ids['custom_field_id'] => 1,
575 'id' => $result['id'],
577 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
579 $this->customFieldDelete($ids['custom_field_id']);
580 $this->customGroupDelete($ids['custom_group_id']);
584 * CRM-12773 - expectation is that civicrm quietly ignores fields without values.
586 public function testCreateWithNULLCustomCRM12773() {
587 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
588 $params = $this->_params
;
589 $params['custom_' . $ids['custom_field_id']] = NULL;
590 $this->callAPISuccess('contact', 'create', $params);
591 $this->customFieldDelete($ids['custom_field_id']);
592 $this->customGroupDelete($ids['custom_group_id']);
596 * CRM-14232 test preferred language set to site default if not passed.
598 public function testCreatePreferredLanguageUnset() {
599 $this->callAPISuccess('Contact', 'create', array(
600 'first_name' => 'Snoop',
601 'last_name' => 'Dog',
602 'contact_type' => 'Individual')
604 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
605 $this->assertEquals('en_US', $result['preferred_language']);
609 * CRM-14232 test preferred language returns setting if not passed.
611 public function testCreatePreferredLanguageSet() {
612 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'fr_FR'));
613 $this->callAPISuccess('Contact', 'create', array(
614 'first_name' => 'Snoop',
615 'last_name' => 'Dog',
616 'contact_type' => 'Individual',
618 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
619 $this->assertEquals('fr_FR', $result['preferred_language']);
623 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
625 public function testCreatePreferredLanguageNull() {
626 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
627 $this->callAPISuccess('Contact', 'create', array(
628 'first_name' => 'Snoop',
629 'last_name' => 'Dog',
630 'contact_type' => 'Individual',
633 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
634 $this->assertEquals(NULL, $result['preferred_language']);
638 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
640 public function testCreatePreferredLanguagePassed() {
641 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
642 $this->callAPISuccess('Contact', 'create', array(
643 'first_name' => 'Snoop',
644 'last_name' => 'Dog',
645 'contact_type' => 'Individual',
646 'preferred_language' => 'en_AU',
648 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
649 $this->assertEquals('en_AU', $result['preferred_language']);
653 * CRM-15792 - create/update datetime field for contact.
655 public function testCreateContactCustomFldDateTime() {
656 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'datetime_test_group'));
657 $dateTime = CRM_Utils_Date
::currentDBDate();
658 //check date custom field is saved along with time when time_format is set
660 'first_name' => 'abc3',
661 'last_name' => 'xyz3',
662 'contact_type' => 'Individual',
663 'email' => 'man3@yahoo.com',
664 'api.CustomField.create' => array(
665 'custom_group_id' => $customGroup['id'],
666 'name' => 'test_datetime',
667 'label' => 'Demo Date',
668 'html_type' => 'Select Date',
669 'data_type' => 'Date',
673 'is_searchable' => 0,
678 $result = $this->callAPISuccess('Contact', 'create', $params);
679 $customFldId = $result['values'][$result['id']]['api.CustomField.create']['id'];
680 $this->assertNotNull($result['id']);
681 $this->assertNotNull($customFldId);
684 'id' => $result['id'],
685 "custom_{$customFldId}" => $dateTime,
686 'api.CustomValue.get' => 1,
689 $result = $this->callAPISuccess('Contact', 'create', $params);
690 $this->assertNotNull($result['id']);
691 $customFldDate = date("YmdHis", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
692 $this->assertNotNull($customFldDate);
693 $this->assertEquals($dateTime, $customFldDate);
694 $customValueId = $result['values'][$result['id']]['api.CustomValue.get']['values'][0]['id'];
695 $dateTime = date('Ymd');
696 //date custom field should not contain time part when time_format is null
698 'id' => $result['id'],
699 'api.CustomField.create' => array(
700 'id' => $customFldId,
701 'html_type' => 'Select Date',
702 'data_type' => 'Date',
705 'api.CustomValue.create' => array(
706 'id' => $customValueId,
707 'entity_id' => $result['id'],
708 "custom_{$customFldId}" => $dateTime,
710 'api.CustomValue.get' => 1,
712 $result = $this->callAPISuccess('Contact', 'create', $params);
713 $this->assertNotNull($result['id']);
714 $customFldDate = date("Ymd", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
715 $customFldTime = date("His", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
716 $this->assertNotNull($customFldDate);
717 $this->assertEquals($dateTime, $customFldDate);
718 $this->assertEquals(000000, $customFldTime);
719 $this->callAPISuccess('Contact', 'create', $params);
724 * Test creating a current employer through API.
726 public function testContactCreateCurrentEmployer() {
727 // Here we will just do the get for set-up purposes.
728 $count = $this->callAPISuccess('contact', 'getcount', array(
729 'organization_name' => 'new employer org',
730 'contact_type' => 'Organization',
732 $this->assertEquals(0, $count);
733 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
734 'current_employer' => 'new employer org',
737 // do it again as an update to check it doesn't cause an error
738 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
739 'current_employer' => 'new employer org',
740 'id' => $employerResult['id'],
744 $this->callAPISuccess('contact', 'getcount', array(
745 'organization_name' => 'new employer org',
746 'contact_type' => 'Organization',
750 $result = $this->callAPISuccess('contact', 'getsingle', array(
751 'id' => $employerResult['id'],
754 $this->assertEquals('new employer org', $result['current_employer']);
759 * Test creating a current employer through API.
761 * Check it will re-activate a de-activated employer
763 public function testContactCreateDuplicateCurrentEmployerEnables() {
764 // Set up - create employer relationship.
765 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
766 'current_employer' => 'new employer org',
769 $relationship = $this->callAPISuccess('relationship', 'get', array(
770 'contact_id_a' => $employerResult['id'],
773 //disable & check it is disabled
774 $this->callAPISuccess('relationship', 'create', array('id' => $relationship['id'], 'is_active' => 0));
775 $this->callAPISuccess('relationship', 'getvalue', array(
776 'id' => $relationship['id'],
777 'return' => 'is_active',
780 // Re-set the current employer - thus enabling the relationship.
781 $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
782 'current_employer' => 'new employer org',
783 'id' => $employerResult['id'],
786 //check is_active is now 1
787 $relationship = $this->callAPISuccess('relationship', 'getsingle', array(
788 'return' => 'is_active',
790 $this->assertEquals(1, $relationship['is_active']);
794 * Check deceased contacts are not retrieved.
796 * Note at time of writing the default is to return default. This should possibly be changed & test added.
798 public function testGetDeceasedRetrieved() {
799 $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
800 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
801 'first_name' => 'bb',
802 'last_name' => 'ccc',
803 'contact_type' => 'Individual',
806 $result = $this->callAPISuccess($this->_entity
, 'get', array('is_deceased' => 0));
807 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
811 * Test that sort works - old syntax.
813 public function testGetSort() {
814 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
815 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
816 'first_name' => 'bb',
817 'last_name' => 'ccc',
818 'contact_type' => 'Individual',
820 $result = $this->callAPISuccess($this->_entity
, 'get', array(
821 'sort' => 'first_name ASC',
822 'return.first_name' => 1,
825 'contact_type' => 'Individual',
828 $this->assertEquals('abc1', $result['values'][0]['first_name']);
829 $result = $this->callAPISuccess($this->_entity
, 'get', array(
830 'sort' => 'first_name DESC',
831 'return.first_name' => 1,
835 $this->assertEquals('bb', $result['values'][0]['first_name']);
837 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
838 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
842 * Test that we can retrieve contacts using array syntax.
844 * I.e 'id' => array('IN' => array('3,4')).
846 public function testGetINIDArray() {
847 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
848 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
849 'first_name' => 'bb',
850 'last_name' => 'ccc',
851 'contact_type' => 'Individual',
853 $c3 = $this->callAPISuccess($this->_entity
, 'create', array(
854 'first_name' => 'hh',
856 'contact_type' => 'Individual',
858 $result = $this->callAPISuccess($this->_entity
, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
859 $this->assertEquals(2, $result['count']);
860 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
861 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
862 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
863 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c3['id']));
867 * Test variants on deleted behaviour.
869 public function testGetDeleted() {
870 $params = $this->_params
;
871 $contact1 = $this->callAPISuccess('contact', 'create', $params);
872 $params['is_deleted'] = 1;
873 $params['last_name'] = 'bcd';
874 $contact2 = $this->callAPISuccess('contact', 'create', $params);
875 $countActive = $this->callAPISuccess('contact', 'getcount', array(
876 'showAll' => 'active',
877 'contact_type' => 'Individual',
879 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all', 'contact_type' => 'Individual'));
880 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash', 'contact_type' => 'Individual'));
881 $countDefault = $this->callAPISuccess('contact', 'getcount', array('contact_type' => 'Individual'));
882 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
883 'contact_type' => 'Individual',
884 'contact_is_deleted' => 1,
886 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
887 'contact_is_deleted' => 0,
888 'contact_type' => 'Individual',
890 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
891 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
892 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected');
893 $this->assertEquals(1, $countActive);
894 $this->assertEquals(1, $countTrash);
895 $this->assertEquals(2, $countAll);
896 $this->assertEquals(1, $countDeleted);
897 $this->assertEquals(1, $countDefault, 'Only active by default in line');
901 * Test that sort works - new syntax.
903 public function testGetSortNewSyntax() {
904 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
905 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
906 'first_name' => 'bb',
907 'last_name' => 'ccc',
908 'contact_type' => 'Individual',
910 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
911 'return' => 'first_name',
912 'contact_type' => 'Individual',
915 'sort' => 'first_name',
918 $this->assertEquals('abc1', $result);
920 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
921 'return' => 'first_name',
922 'contact_type' => 'Individual',
925 'sort' => 'first_name DESC',
928 $this->assertEquals('bb', $result);
930 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
931 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
935 * Test sort and limit for chained relationship get.
937 * https://issues.civicrm.org/jira/browse/CRM-15983
939 public function testSortLimitChainedRelationshipGetCRM15983() {
941 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
942 'first_name' => 'Jules',
943 'last_name' => 'Smos',
944 'contact_type' => 'Individual',
947 // Create another contact with two relationships.
948 $create_params = array(
949 'first_name' => 'Jos',
950 'last_name' => 'Smos',
951 'contact_type' => 'Individual',
952 'api.relationship.create' => array(
954 'contact_id_a' => '$value.id',
955 'contact_id_b' => $create_result_1['id'],
957 'relationship_type_id' => 2,
958 'start_date' => '2005-01-12',
959 'end_date' => '2006-01-11',
960 'description' => 'old',
963 'contact_id_a' => '$value.id',
964 'contact_id_b' => $create_result_1['id'],
965 // spouse of (was married twice :))
966 'relationship_type_id' => 2,
967 'start_date' => '2006-07-01',
968 'end_date' => '2010-07-01',
969 'description' => 'new',
973 $create_result = $this->callAPISuccess('contact', 'create', $create_params);
975 // Try to retrieve the contact and the most recent relationship.
978 'id' => $create_result['id'],
979 'api.relationship.get' => array(
980 'contact_id_a' => '$value.id',
983 'sort' => 'start_date DESC',
986 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
989 $this->callAPISuccess('contact', 'delete', array(
990 'id' => $create_result['id'],
994 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
995 $this->assertEquals('new', $get_result['api.relationship.get']['values'][0]['description']);
999 * Test apostrophe works in get & create.
1001 public function testGetApostropheCRM10857() {
1002 $params = array_merge($this->_params
, array('last_name' => "O'Connor"));
1003 $this->callAPISuccess($this->_entity
, 'create', $params);
1004 $result = $this->callAPISuccess($this->_entity
, 'getsingle', array(
1005 'last_name' => "O'Connor",
1008 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__
);
1012 * Test retrieval by addressee id.
1014 public function testGetByAddresseeID() {
1015 $individual1ID = $this->individualCreate([
1016 'skip_greeting_processing' => 1,
1017 'addressee_id' => 'null',
1018 'email_greeting_id' => 'null',
1019 'postal_greeting_id' => 'null'
1021 $individual2ID = $this->individualCreate();
1023 $this->assertEquals($individual1ID,
1024 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'addressee_id' => ['IS NULL' => 1], 'return' => 'id'])
1026 $this->assertEquals($individual1ID,
1027 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'email_greeting_id' => ['IS NULL' => 1], 'return' => 'id'])
1029 $this->assertEquals($individual1ID,
1030 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'postal_greeting_id' => ['IS NULL' => 1], 'return' => 'id'])
1033 $this->assertEquals($individual2ID,
1034 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'addressee_id' => ['NOT NULL' => 1], 'return' => 'id'])
1039 * Check with complete array + custom field.
1041 * Note that the test is written on purpose without any
1042 * variables specific to participant so it can be replicated into other entities
1043 * and / or moved to the automated test suite
1045 public function testGetWithCustom() {
1046 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1048 $params = $this->_params
;
1049 $params['custom_' . $ids['custom_field_id']] = "custom string";
1050 $description = "This demonstrates setting a custom field through the API.";
1051 $subfile = "CustomFieldGet";
1052 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
1054 $check = $this->callAPIAndDocument($this->_entity
, 'get', array(
1055 'return.custom_' . $ids['custom_field_id'] => 1,
1056 'id' => $result['id'],
1057 ), __FUNCTION__
, __FILE__
, $description, $subfile);
1059 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
1060 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
1061 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
1062 $this->customFieldDelete($ids['custom_field_id']);
1063 $this->customGroupDelete($ids['custom_group_id']);
1067 * Check with complete array + custom field.
1069 * Note that the test is written on purpose without any
1070 * variables specific to participant so it can be replicated into other entities
1071 * and / or moved to the automated test suite
1073 public function testGetWithCustomReturnSyntax() {
1074 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1076 $params = $this->_params
;
1077 $params['custom_' . $ids['custom_field_id']] = "custom string";
1078 $description = "This demonstrates setting a custom field through the API.";
1079 $subfile = "CustomFieldGetReturnSyntaxVariation";
1080 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
1081 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
1082 $check = $this->callAPIAndDocument($this->_entity
, 'get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1084 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
1085 $this->customFieldDelete($ids['custom_field_id']);
1086 $this->customGroupDelete($ids['custom_group_id']);
1090 * Check that address name, ID is returned if required.
1092 public function testGetReturnAddress() {
1093 $contactID = $this->individualCreate();
1094 $result = $this->callAPISuccess('address', 'create', array(
1095 'contact_id' => $contactID,
1096 'address_name' => 'My house',
1097 'location_type_id' => 'Home',
1098 'street_address' => '1 my road',
1100 $addressID = $result['id'];
1102 $result = $this->callAPISuccessGetSingle('contact', array(
1103 'return' => 'address_name, street_address, address_id',
1106 $this->assertEquals($addressID, $result['address_id']);
1107 $this->assertEquals('1 my road', $result['street_address']);
1108 $this->assertEquals('My house', $result['address_name']);
1113 * Test group filter syntaxes.
1115 public function testGetGroupIDFromContact() {
1116 $groupId = $this->groupCreate();
1118 'email' => 'man2@yahoo.com',
1119 'contact_type' => 'Individual',
1120 'location_type_id' => 1,
1121 'api.group_contact.create' => array('group_id' => $groupId),
1124 $this->callAPISuccess('contact', 'create', $params);
1125 // testing as integer
1127 'filter.group_id' => $groupId,
1128 'contact_type' => 'Individual',
1130 $result = $this->callAPISuccess('contact', 'get', $params);
1131 $this->assertEquals(1, $result['count']);
1132 // group 26 doesn't exist, but we can still search contacts in it.
1134 'filter.group_id' => 26,
1135 'contact_type' => 'Individual',
1137 $this->callAPISuccess('contact', 'get', $params);
1138 // testing as string
1140 'filter.group_id' => "$groupId, 26",
1141 'contact_type' => 'Individual',
1143 $result = $this->callAPISuccess('contact', 'get', $params);
1144 $this->assertEquals(1, $result['count']);
1146 'filter.group_id' => "26,27",
1147 'contact_type' => 'Individual',
1149 $this->callAPISuccess('contact', 'get', $params);
1151 // testing as string
1153 'filter.group_id' => array($groupId, 26),
1154 'contact_type' => 'Individual',
1156 $result = $this->callAPISuccess('contact', 'get', $params);
1157 $this->assertEquals(1, $result['count']);
1159 //test in conjunction with other criteria
1161 'filter.group_id' => array($groupId, 26),
1162 'contact_type' => 'Organization',
1164 $this->callAPISuccess('contact', 'get', $params);
1166 'filter.group_id' => array(26, 27),
1167 'contact_type' => 'Individual',
1169 $result = $this->callAPISuccess('contact', 'get', $params);
1170 $this->assertEquals(0, $result['count']);
1174 * Verify that attempt to create individual contact with two chained websites succeeds.
1176 public function testCreateIndividualWithContributionDottedSyntax() {
1177 $description = "This demonstrates the syntax to create 2 chained entities.";
1178 $subFile = "ChainTwoWebsites";
1180 'first_name' => 'abc3',
1181 'last_name' => 'xyz3',
1182 'contact_type' => 'Individual',
1183 'email' => 'man3@yahoo.com',
1184 'api.contribution.create' => array(
1185 'receive_date' => '2010-01-01',
1186 'total_amount' => 100.00,
1187 'financial_type_id' => $this->_financialTypeId
,
1188 'payment_instrument_id' => 1,
1189 'non_deductible_amount' => 10.00,
1190 'fee_amount' => 50.00,
1191 'net_amount' => 90.00,
1193 'invoice_id' => 67990,
1195 'contribution_status_id' => 1,
1196 'skipCleanMoney' => 1,
1198 'api.website.create' => array(
1199 'url' => "http://civicrm.org",
1201 'api.website.create.2' => array(
1202 'url' => "http://chained.org",
1206 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
1208 // checking child function result not covered in callAPIAndDocument
1209 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
1210 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url']);
1211 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url']);
1213 // delete the contact
1214 $this->callAPISuccess('contact', 'delete', $result);
1218 * Verify that attempt to create individual contact with chained contribution and website succeeds.
1220 public function testCreateIndividualWithContributionChainedArrays() {
1222 'first_name' => 'abc3',
1223 'last_name' => 'xyz3',
1224 'contact_type' => 'Individual',
1225 'email' => 'man3@yahoo.com',
1226 'api.contribution.create' => array(
1227 'receive_date' => '2010-01-01',
1228 'total_amount' => 100.00,
1229 'financial_type_id' => $this->_financialTypeId
,
1230 'payment_instrument_id' => 1,
1231 'non_deductible_amount' => 10.00,
1232 'fee_amount' => 50.00,
1233 'net_amount' => 90.00,
1235 'invoice_id' => 67890,
1237 'contribution_status_id' => 1,
1238 'skipCleanMoney' => 1,
1240 'api.website.create' => array(
1242 'url' => "http://civicrm.org",
1245 'url' => "http://chained.org",
1246 'website_type_id' => 2,
1251 $description = "Demonstrates creating two websites as an array.";
1252 $subfile = "ChainTwoWebsitesSyntax2";
1253 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1255 // the callAndDocument doesn't check the chained call
1256 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error']);
1257 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url']);
1258 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url']);
1260 $this->callAPISuccess('contact', 'delete', $result);
1264 * Test for direction when chaining relationships.
1266 * https://issues.civicrm.org/jira/browse/CRM-16084
1268 public function testDirectionChainingRelationshipsCRM16084() {
1269 // Some contact, called Jules.
1270 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
1271 'first_name' => 'Jules',
1272 'last_name' => 'Smos',
1273 'contact_type' => 'Individual',
1276 // Another contact: Jos, child of Jules.
1277 $create_params = array(
1278 'first_name' => 'Jos',
1279 'last_name' => 'Smos',
1280 'contact_type' => 'Individual',
1281 'api.relationship.create' => array(
1283 'contact_id_a' => '$value.id',
1284 'contact_id_b' => $create_result_1['id'],
1286 'relationship_type_id' => 1,
1290 $create_result_2 = $this->callAPISuccess('contact', 'create', $create_params);
1292 // Mia is the child of Jos.
1293 $create_params = array(
1294 'first_name' => 'Mia',
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_2['id'],
1302 'relationship_type_id' => 1,
1306 $create_result_3 = $this->callAPISuccess('contact', 'create', $create_params);
1308 // Get Jos and his children.
1309 $get_params = array(
1311 'id' => $create_result_2['id'],
1312 'api.relationship.get' => array(
1313 'contact_id_b' => '$value.id',
1314 'relationship_type_id' => 1,
1317 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
1320 $this->callAPISuccess('contact', 'delete', array(
1321 'id' => $create_result_1['id'],
1323 $this->callAPISuccess('contact', 'delete', array(
1324 'id' => $create_result_2['id'],
1326 $this->callAPISuccess('contact', 'delete', array(
1327 'id' => $create_result_2['id'],
1331 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
1332 $this->assertEquals($create_result_3['id'], $get_result['api.relationship.get']['values'][0]['contact_id_a']);
1336 * Verify that attempt to create individual contact with first, and last names and email succeeds.
1338 public function testCreateIndividualWithNameEmail() {
1340 'first_name' => 'abc3',
1341 'last_name' => 'xyz3',
1342 'contact_type' => 'Individual',
1343 'email' => 'man3@yahoo.com',
1346 $contact = $this->callAPISuccess('contact', 'create', $params);
1348 $this->callAPISuccess('contact', 'delete', $contact);
1352 * Verify that attempt to create individual contact with no data fails.
1354 public function testCreateIndividualWithOutNameEmail() {
1356 'contact_type' => 'Individual',
1358 $this->callAPIFailure('contact', 'create', $params);
1362 * Test create individual contact with first &last names, email and location type succeeds.
1364 public function testCreateIndividualWithNameEmailLocationType() {
1366 'first_name' => 'abc4',
1367 'last_name' => 'xyz4',
1368 'email' => 'man4@yahoo.com',
1369 'contact_type' => 'Individual',
1370 'location_type_id' => 1,
1372 $result = $this->callAPISuccess('contact', 'create', $params);
1374 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
1378 * Verify that when changing employers the old employer relationship becomes inactive.
1380 public function testCreateIndividualWithEmployer() {
1381 $employer = $this->organizationCreate();
1382 $employer2 = $this->organizationCreate();
1385 'email' => 'man4@yahoo.com',
1386 'contact_type' => 'Individual',
1387 'employer_id' => $employer,
1390 $result = $this->callAPISuccess('contact', 'create', $params);
1391 $relationships = $this->callAPISuccess('relationship', 'get', array(
1392 'contact_id_a' => $result['id'],
1396 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1398 // Add more random relationships to make the test more realistic
1399 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
1400 $relTypeId = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
1401 $this->callAPISuccess('relationship', 'create', array(
1402 'contact_id_a' => $result['id'],
1403 'contact_id_b' => $this->organizationCreate(),
1405 'relationship_type_id' => $relTypeId,
1409 // Add second employer
1410 $params['employer_id'] = $employer2;
1411 $params['id'] = $result['id'];
1412 $result = $this->callAPISuccess('contact', 'create', $params);
1414 $relationships = $this->callAPISuccess('relationship', 'get', array(
1415 'contact_id_a' => $result['id'],
1420 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1424 * Verify that attempt to create household contact with details succeeds.
1426 public function testCreateHouseholdDetails() {
1428 'household_name' => 'abc8\'s House',
1429 'nick_name' => 'x House',
1430 'email' => 'man8@yahoo.com',
1431 'contact_type' => 'Household',
1434 $contact = $this->callAPISuccess('contact', 'create', $params);
1436 $this->callAPISuccess('contact', 'delete', $contact);
1440 * Verify that attempt to create household contact with inadequate details fails.
1442 public function testCreateHouseholdInadequateDetails() {
1444 'nick_name' => 'x House',
1445 'email' => 'man8@yahoo.com',
1446 'contact_type' => 'Household',
1448 $this->callAPIFailure('contact', 'create', $params);
1452 * Verify successful update of individual contact.
1454 public function testUpdateIndividualWithAll() {
1455 // Insert a row in civicrm_contact creating individual contact.
1456 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1457 $op->execute($this->_dbconn
,
1458 $this->createXMLDataSet(
1459 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1465 'first_name' => 'abcd',
1466 'contact_type' => 'Individual',
1467 'nick_name' => 'This is nickname first',
1468 'do_not_email' => '1',
1469 'do_not_phone' => '1',
1470 'do_not_mail' => '1',
1471 'do_not_trade' => '1',
1472 'legal_identifier' => 'ABC23853ZZ2235',
1473 'external_identifier' => '1928837465',
1474 'image_URL' => 'http://some.url.com/image.jpg',
1475 'home_url' => 'http://www.example.org',
1479 $this->callAPISuccess('Contact', 'Update', $params);
1480 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
1481 unset($params['contact_id']);
1482 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
1483 //reducing this test partially back to api v2 level to get it through
1484 unset($params['home_url']);
1485 foreach ($params as $key => $value) {
1486 $this->assertEquals($value, $getResult['values'][23][$key]);
1488 // Check updated civicrm_contact against expected.
1489 $expected = $this->createXMLDataSet(
1490 dirname(__FILE__
) . '/dataset/contact_ind_upd.xml'
1492 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1495 $actual->addTable('civicrm_contact');
1496 $expected->matches($actual);
1500 * Verify successful update of organization contact.
1502 public function testUpdateOrganizationWithAll() {
1503 // Insert a row in civicrm_contact creating organization contact
1504 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1505 $op->execute($this->_dbconn
,
1506 $this->createXMLDataSet(
1507 dirname(__FILE__
) . '/dataset/contact_org.xml'
1513 'organization_name' => 'WebAccess India Pvt Ltd',
1514 'legal_name' => 'WebAccess',
1515 'sic_code' => 'ABC12DEF',
1516 'contact_type' => 'Organization',
1519 $this->callAPISuccess('Contact', 'Update', $params);
1521 // Check updated civicrm_contact against expected.
1522 $expected = $this->createXMLDataSet(
1523 dirname(__FILE__
) . '/dataset/contact_org_upd.xml'
1525 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1528 $actual->addTable('civicrm_contact');
1529 $expected->matches($actual);
1533 * Test merging 2 organizations.
1535 * CRM-20421: This test make sure that inherited memberships are deleted upon merging organization.
1537 public function testMergeOrganizations() {
1538 $organizationID1 = $this->organizationCreate(array(), 0);
1539 $organizationID2 = $this->organizationCreate(array(), 1);
1540 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
1541 'employer_id' => $organizationID1,
1544 $contact = $contact["values"][$contact["id"]];
1546 $membershipType = $this->createEmployerOfMembership();
1547 $membershipParams = array(
1548 'membership_type_id' => $membershipType["id"],
1549 'contact_id' => $organizationID1,
1550 'start_date' => "01/01/2015",
1551 'join_date' => "01/01/2010",
1552 'end_date' => "12/31/2015",
1554 $ownermembershipid = $this->contactMembershipCreate($membershipParams);
1556 $contactmembership = $this->callAPISuccess("membership", "getsingle", array(
1557 "contact_id" => $contact["id"],
1560 $this->assertEquals($ownermembershipid, $contactmembership["owner_membership_id"], "Contact membership must be inherited from Organization");
1562 CRM_Dedupe_Merger
::moveAllBelongings($organizationID2, $organizationID1, array(
1563 "move_rel_table_memberships" => "0",
1564 "move_rel_table_relationships" => "1",
1565 "main_details" => array(
1566 "contact_id" => $organizationID2,
1567 "contact_type" => "Organization",
1569 "other_details" => array(
1570 "contact_id" => $organizationID1,
1571 "contact_type" => "Organization",
1575 $contactmembership = $this->callAPISuccess("membership", "get", array(
1576 "contact_id" => $contact["id"],
1579 $this->assertEquals(0, $contactmembership["count"], "Contact membership must be deleted after merging organization without memberships.");
1582 private function createEmployerOfMembership() {
1584 'domain_id' => CRM_Core_Config
::domainID(),
1585 'name' => 'Organization Membership',
1586 'description' => NULL,
1587 'member_of_contact_id' => 1,
1588 'financial_type_id' => 1,
1589 'minimum_fee' => 10,
1590 'duration_unit' => 'year',
1591 'duration_interval' => 1,
1592 'period_type' => 'rolling',
1593 'relationship_type_id' => 5,
1594 'relationship_direction' => 'b_a',
1595 'visibility' => 'Public',
1598 $membershipType = $this->callAPISuccess('membership_type', 'create', $params);
1599 return $membershipType["values"][$membershipType["id"]];
1603 * Verify successful update of household contact.
1605 public function testUpdateHouseholdWithAll() {
1606 // Insert a row in civicrm_contact creating household contact
1607 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1608 $op->execute($this->_dbconn
,
1609 $this->createXMLDataSet(
1610 dirname(__FILE__
) . '/dataset/contact_hld.xml'
1616 'household_name' => 'ABC household',
1617 'nick_name' => 'ABC House',
1618 'contact_type' => 'Household',
1621 $result = $this->callAPISuccess('Contact', 'Update', $params);
1624 'contact_type' => 'Household',
1626 'sort_name' => 'ABC household',
1627 'display_name' => 'ABC household',
1628 'nick_name' => 'ABC House',
1630 $this->getAndCheck($expected, $result['id'], 'contact');
1634 * Test civicrm_update() without contact type.
1636 * Deliberately exclude contact_type as it should still cope using civicrm_api.
1640 public function testUpdateCreateWithID() {
1641 // Insert a row in civicrm_contact creating individual contact.
1642 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1643 $op->execute($this->_dbconn
,
1644 $this->createXMLDataSet(
1645 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1651 'first_name' => 'abcd',
1652 'last_name' => 'wxyz',
1654 $this->callAPISuccess('Contact', 'Update', $params);
1658 * Test civicrm_contact_delete() with no contact ID.
1660 public function testContactDeleteNoID() {
1664 $this->callAPIFailure('contact', 'delete', $params);
1668 * Test civicrm_contact_delete() with error.
1670 public function testContactDeleteError() {
1671 $params = array('contact_id' => 999);
1672 $this->callAPIFailure('contact', 'delete', $params);
1676 * Test civicrm_contact_delete().
1678 public function testContactDelete() {
1679 $contactID = $this->individualCreate();
1683 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__
, __FILE__
);
1687 * Test civicrm_contact_get() return only first name.
1689 public function testContactGetRetFirst() {
1690 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1692 'contact_id' => $contact['id'],
1693 'return_first_name' => TRUE,
1694 'sort' => 'first_name',
1696 $result = $this->callAPISuccess('contact', 'get', $params);
1697 $this->assertEquals(1, $result['count']);
1698 $this->assertEquals($contact['id'], $result['id']);
1699 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1703 * Test civicrm_contact_get() return only first name & last name.
1705 * Use comma separated string return with a space.
1707 public function testContactGetReturnFirstLast() {
1708 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1710 'contact_id' => $contact['id'],
1711 'return' => 'first_name, last_name',
1713 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1714 $this->assertEquals('abc1', $result['first_name']);
1715 $this->assertEquals('xyz1', $result['last_name']);
1716 //check that other defaults not returns
1717 $this->assertArrayNotHasKey('sort_name', $result);
1719 'contact_id' => $contact['id'],
1720 'return' => 'first_name,last_name',
1722 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1723 $this->assertEquals('abc1', $result['first_name']);
1724 $this->assertEquals('xyz1', $result['last_name']);
1725 //check that other defaults not returns
1726 $this->assertArrayNotHasKey('sort_name', $result);
1730 * Test civicrm_contact_get() return only first name & last name.
1732 * Use comma separated string return without a space
1734 public function testContactGetReturnFirstLastNoComma() {
1735 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1737 'contact_id' => $contact['id'],
1738 'return' => 'first_name,last_name',
1740 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1741 $this->assertEquals('abc1', $result['first_name']);
1742 $this->assertEquals('xyz1', $result['last_name']);
1743 //check that other defaults not returns
1744 $this->assertArrayNotHasKey('sort_name', $result);
1748 * Test civicrm_contact_get() with default return properties.
1750 public function testContactGetRetDefault() {
1751 $contactID = $this->individualCreate();
1753 'contact_id' => $contactID,
1754 'sort' => 'first_name',
1756 $result = $this->callAPISuccess('contact', 'get', $params);
1757 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1758 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1762 * Test civicrm_contact_getquick() with empty name param.
1764 public function testContactGetQuick() {
1765 // Insert a row in civicrm_contact creating individual contact.
1766 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1767 $op->execute($this->_dbconn
,
1768 $this->createXMLDataSet(
1769 dirname(__FILE__
) . '/dataset/contact_17.xml'
1772 $op->execute($this->_dbconn
,
1773 $this->createXMLDataSet(
1774 dirname(__FILE__
) . '/dataset/email_contact_17.xml'
1781 $result = $this->callAPISuccess('contact', 'getquick', $params);
1782 $this->assertEquals(17, $result['values'][0]['id']);
1786 * Test civicrm_contact_get) with empty params.
1788 public function testContactGetEmptyParams() {
1789 $this->callAPISuccess('contact', 'get', array());
1793 * Test civicrm_contact_get(,true) with no matches.
1795 public function testContactGetOldParamsNoMatches() {
1796 // Insert a row in civicrm_contact creating contact 17.
1797 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1798 $op->execute($this->_dbconn
,
1799 $this->createXMLDataSet(
1800 dirname(__FILE__
) . '/dataset/contact_17.xml'
1805 'first_name' => 'Fred',
1807 $result = $this->callAPISuccess('contact', 'get', $params);
1808 $this->assertEquals(0, $result['count']);
1812 * Test civicrm_contact_get(,true) with one match.
1814 public function testContactGetOldParamsOneMatch() {
1815 // Insert a row in civicrm_contact creating contact 17
1816 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1817 $op->execute($this->_dbconn
,
1818 $this->createXMLDataSet(dirname(__FILE__
) . '/dataset/contact_17.xml'
1823 'first_name' => 'Test',
1825 $result = $this->callAPISuccess('contact', 'get', $params);
1826 $this->assertEquals(17, $result['values'][17]['contact_id']);
1827 $this->assertEquals(17, $result['id']);
1831 * Test civicrm_contact_search_count().
1833 public function testContactGetEmail() {
1835 'email' => 'man2@yahoo.com',
1836 'contact_type' => 'Individual',
1837 'location_type_id' => 1,
1840 $contact = $this->callAPISuccess('contact', 'create', $params);
1843 'email' => 'man2@yahoo.com',
1845 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
);
1846 $this->assertEquals('man2@yahoo.com', $result['values'][$result['id']]['email']);
1848 $this->callAPISuccess('contact', 'delete', $contact);
1852 * Ensure consistent return format for option group fields.
1854 public function testSetPreferredCommunicationNull() {
1855 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
1856 'preferred_communication_method' => array('Phone', 'SMS'),
1858 $preferredCommunicationMethod = $this->callAPISuccessGetValue('Contact', array(
1859 'id' => $contact['id'],
1860 'return' => 'preferred_communication_method',
1862 $this->assertNotEmpty($preferredCommunicationMethod);
1863 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
1864 'preferred_communication_method' => 'null',
1865 'id' => $contact['id'],
1867 $preferredCommunicationMethod = $this->callAPISuccessGetValue('Contact', array(
1868 'id' => $contact['id'],
1869 'return' => 'preferred_communication_method',
1871 $this->assertEmpty($preferredCommunicationMethod);
1875 * Ensure consistent return format for option group fields.
1877 public function testPseudoFields() {
1879 'preferred_communication_method' => array('Phone', 'SMS'),
1880 'preferred_language' => 'en_US',
1881 'gender_id' => 'Female',
1882 'prefix_id' => 'Mrs.',
1883 'suffix_id' => 'II',
1884 'communication_style_id' => 'Formal',
1887 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, $params));
1889 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
1890 $this->assertEquals('Both', $result['preferred_mail_format']);
1892 $this->assertEquals('en_US', $result['preferred_language']);
1893 $this->assertEquals(1, $result['communication_style_id']);
1894 $this->assertEquals(1, $result['gender_id']);
1895 $this->assertEquals('Female', $result['gender']);
1896 $this->assertEquals('Mrs.', $result['individual_prefix']);
1897 $this->assertEquals(1, $result['prefix_id']);
1898 $this->assertEquals('II', $result['individual_suffix']);
1899 $this->assertEquals(CRM_Core_PseudoConstant
::getKey("CRM_Contact_BAO_Contact", 'suffix_id', 'II'), $result['suffix_id']);
1900 $this->callAPISuccess('contact', 'delete', $contact);
1901 $this->assertEquals(array(
1902 CRM_Core_PseudoConstant
::getKey("CRM_Contact_BAO_Contact", 'preferred_communication_method', 'Phone'),
1903 CRM_Core_PseudoConstant
::getKey("CRM_Contact_BAO_Contact", 'preferred_communication_method', 'SMS'),
1904 ), $result['preferred_communication_method']);
1909 * Test birth date parameters.
1911 * These include value, array & birth_date_high, birth_date_low
1914 public function testContactGetBirthDate() {
1915 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 2 years')));
1916 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 5 years')));
1917 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month -20 years')));
1919 $result = $this->callAPISuccess('contact', 'get', array());
1920 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1921 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1922 $this->assertEquals(1, $result['count']);
1923 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1924 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1925 $this->assertEquals(1, $result['count']);
1926 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1927 $result = $this->callAPISuccess('contact', 'get', array(
1928 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
1929 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
1931 $this->assertEquals(1, $result['count']);
1932 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1933 $result = $this->callAPISuccess('contact', 'get', array(
1934 'birth_date_low' => '-6 years',
1935 'birth_date_high' => '- 3 years',
1937 $this->assertEquals(1, $result['count']);
1938 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1942 * Test Address parameters
1944 * This include state_province, state_province_name, country
1946 public function testContactGetWithAddressFields() {
1947 $individuals = array(
1949 'first_name' => 'abc1',
1950 'contact_type' => 'Individual',
1951 'last_name' => 'xyz1',
1952 'api.address.create' => array(
1953 'country' => 'United States',
1954 'state_province_id' => 'Michigan',
1955 'location_type_id' => 1,
1959 'first_name' => 'abc2',
1960 'contact_type' => 'Individual',
1961 'last_name' => 'xyz2',
1962 'api.address.create' => array(
1963 'country' => 'United States',
1964 'state_province_id' => 'Alabama',
1965 'location_type_id' => 1,
1969 foreach ($individuals as $params) {
1970 $contact = $this->callAPISuccess('contact', 'create', $params);
1973 // Check whether Contact get API return successfully with below Address params.
1974 $fieldsToTest = array(
1975 'state_province_name' => 'Michigan',
1976 'state_province' => 'Michigan',
1977 'country' => 'United States',
1978 'state_province_name' => array('IN' => array('Michigan', 'Alabama')),
1979 'state_province' => array('IN' => array('Michigan', 'Alabama')),
1981 foreach ($fieldsToTest as $field => $value) {
1983 'id' => $contact['id'],
1986 $result = $this->callAPISuccess('Contact', 'get', $getParams);
1987 $this->assertEquals(1, $result['count']);
1992 * Test Deceased date parameters.
1994 * These include value, array & Deceased_date_high, Deceased date_low
1997 public function testContactGetDeceasedDate() {
1998 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 2 years')));
1999 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 5 years')));
2000 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month -20 years')));
2002 $result = $this->callAPISuccess('contact', 'get', array());
2003 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
2004 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
2005 $this->assertEquals(1, $result['count']);
2006 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
2007 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
2008 $this->assertEquals(1, $result['count']);
2009 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
2010 $result = $this->callAPISuccess('contact', 'get', array(
2011 'deceased_date_low' => '-6 years',
2012 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
2014 $this->assertEquals(1, $result['count']);
2015 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
2019 * Test for Contact.get id=@user:username.
2021 public function testContactGetByUsername() {
2022 // Setup - create contact with a uf-match.
2023 $cid = $this->individualCreate(array(
2024 'contact_type' => 'Individual',
2025 'first_name' => 'testGetByUsername',
2026 'last_name' => 'testGetByUsername',
2029 $ufMatchParams = array(
2030 'domain_id' => CRM_Core_Config
::domainID(),
2032 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
2033 'contact_id' => $cid,
2035 $ufMatch = CRM_Core_BAO_UFMatch
::create($ufMatchParams);
2036 $this->assertTrue(is_numeric($ufMatch->id
));
2038 // setup - mock the calls to CRM_Utils_System_*::getUfId
2039 $mockFunction = $this->mockMethod
;
2040 $userSystem = $this->$mockFunction('CRM_Utils_System_UnitTests', array('getUfId'));
2041 $userSystem->expects($this->once())
2043 ->with($this->equalTo('exampleUser'))
2044 ->will($this->returnValue(99));
2045 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
2048 $result = $this->callAPISuccess('Contact', 'get', array(
2049 'id' => '@user:exampleUser',
2051 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
2055 * Test to check return works OK.
2057 public function testContactGetReturnValues() {
2058 $extraParams = array(
2059 'nick_name' => 'Bob',
2061 'email' => 'e@mail.com',
2063 $contactID = $this->individualCreate($extraParams);
2064 //actually it turns out the above doesn't create a phone
2065 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
2066 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
2067 foreach ($extraParams as $key => $value) {
2068 $this->assertEquals($result[$key], $value);
2070 //now we check they are still returned with 'return' key
2071 $result = $this->callAPISuccess('contact', 'getsingle', array(
2073 'return' => array_keys($extraParams),
2075 foreach ($extraParams as $key => $value) {
2076 $this->assertEquals($result[$key], $value);
2081 * Test creating multiple phones using chaining.
2083 * @throws \Exception
2085 public function testCRM13252MultipleChainedPhones() {
2086 $contactID = $this->householdCreate();
2087 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
2089 'contact_id' => $contactID,
2090 'household_name' => 'Household 1',
2091 'contact_type' => 'Household',
2092 'api.phone.create' => array(
2094 'phone' => '111-111-1111',
2095 'location_type_id' => 1,
2096 'phone_type_id' => 1,
2099 'phone' => '222-222-2222',
2100 'location_type_id' => 1,
2101 'phone_type_id' => 2,
2105 $this->callAPISuccess('contact', 'create', $params);
2106 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
2111 * Test for Contact.get id=@user:username (with an invalid username).
2113 public function testContactGetByUnknownUsername() {
2114 // setup - mock the calls to CRM_Utils_System_*::getUfId
2115 $mockFunction = $this->mockMethod
;
2116 $userSystem = $this->$mockFunction('CRM_Utils_System_UnitTests', array('getUfId'));
2117 $userSystem->expects($this->once())
2119 ->with($this->equalTo('exampleUser'))
2120 ->will($this->returnValue(NULL));
2121 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
2124 $result = $this->callAPIFailure('Contact', 'get', array(
2125 'id' => '@user:exampleUser',
2127 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
2131 * Verify attempt to create individual with chained arrays and sequential.
2133 public function testGetIndividualWithChainedArraysAndSequential() {
2134 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
2135 $params['custom_' . $ids['custom_field_id']] = "custom string";
2137 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2140 'first_name' => 'abc3',
2141 'last_name' => 'xyz3',
2142 'contact_type' => 'Individual',
2143 'email' => 'man3@yahoo.com',
2144 'api.website.create' => array(
2146 'url' => "http://civicrm.org",
2149 'url' => "https://civicrm.org",
2154 $result = $this->callAPISuccess('Contact', 'create', $params);
2156 // delete the contact and custom groups
2157 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
2158 $this->customGroupDelete($ids['custom_group_id']);
2159 $this->customGroupDelete($moreIDs['custom_group_id']);
2161 $this->assertEquals($result['id'], $result['values'][0]['id']);
2162 $this->assertArrayKeyExists('api.website.create', $result['values'][0]);
2166 * Verify attempt to create individual with chained arrays.
2168 public function testGetIndividualWithChainedArrays() {
2169 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
2170 $params['custom_' . $ids['custom_field_id']] = "custom string";
2172 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2173 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
2174 $subfile = "APIChainedArray";
2176 'first_name' => 'abc3',
2177 'last_name' => 'xyz3',
2178 'contact_type' => 'Individual',
2179 'email' => 'man3@yahoo.com',
2180 'api.contribution.create' => array(
2181 'receive_date' => '2010-01-01',
2182 'total_amount' => 100.00,
2183 'financial_type_id' => 1,
2184 'payment_instrument_id' => 1,
2185 'non_deductible_amount' => 10.00,
2186 'fee_amount' => 50.00,
2187 'net_amount' => 90.00,
2189 'invoice_id' => 67890,
2191 'contribution_status_id' => 1,
2193 'api.contribution.create.1' => array(
2194 'receive_date' => '2011-01-01',
2195 'total_amount' => 120.00,
2196 'financial_type_id' => $this->_financialTypeId
= 1,
2197 'payment_instrument_id' => 1,
2198 'non_deductible_amount' => 10.00,
2199 'fee_amount' => 50.00,
2200 'net_amount' => 90.00,
2202 'invoice_id' => 67830,
2204 'contribution_status_id' => 1,
2206 'api.website.create' => array(
2208 'url' => "http://civicrm.org",
2213 $result = $this->callAPISuccess('Contact', 'create', $params);
2215 'id' => $result['id'],
2216 'api.website.get' => array(),
2217 'api.Contribution.get' => array(
2218 'total_amount' => '120.00',
2220 'api.CustomValue.get' => 1,
2221 'api.Note.get' => 1,
2223 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2224 // delete the contact
2225 $this->callAPISuccess('contact', 'delete', $result);
2226 $this->customGroupDelete($ids['custom_group_id']);
2227 $this->customGroupDelete($moreIDs['custom_group_id']);
2228 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
2229 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
2233 * Verify attempt to create individual with chained arrays and sequential.
2235 * See https://issues.civicrm.org/jira/browse/CRM-15815
2237 public function testCreateIndividualWithChainedArrayAndSequential() {
2240 'first_name' => 'abc5',
2241 'last_name' => 'xyz5',
2242 'contact_type' => 'Individual',
2243 'email' => 'woman5@yahoo.com',
2244 'api.phone.create' => array(
2245 array('phone' => '03-231 07 95'),
2246 array('phone' => '03-232 51 62'),
2248 'api.website.create' => array(
2249 'url' => 'http://civicrm.org',
2252 $result = $this->callAPISuccess('Contact', 'create', $params);
2254 // I could try to parse the result to see whether the two phone numbers
2255 // and the website are there, but I am not sure about the correct format.
2256 // So I will just fetch it again before checking.
2257 // See also http://forum.civicrm.org/index.php/topic,35393.0.html
2260 'id' => $result['id'],
2261 'api.website.get' => array(),
2262 'api.phone.get' => array(),
2264 $result = $this->callAPISuccess('Contact', 'get', $params);
2266 // delete the contact
2267 $this->callAPISuccess('contact', 'delete', $result);
2269 $this->assertEquals(2, $result['values'][0]['api.phone.get']['count']);
2270 $this->assertEquals(1, $result['values'][0]['api.website.get']['count']);
2274 * Test retrieving an individual with chained array syntax.
2276 public function testGetIndividualWithChainedArraysFormats() {
2277 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
2278 $subfile = "APIChainedArrayFormats";
2279 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
2280 $params['custom_' . $ids['custom_field_id']] = "custom string";
2282 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2284 'first_name' => 'abc3',
2285 'last_name' => 'xyz3',
2286 'contact_type' => 'Individual',
2287 'email' => 'man3@yahoo.com',
2288 'api.contribution.create' => array(
2289 'receive_date' => '2010-01-01',
2290 'total_amount' => 100.00,
2291 'financial_type_id' => $this->_financialTypeId
,
2292 'payment_instrument_id' => 1,
2293 'non_deductible_amount' => 10.00,
2294 'fee_amount' => 50.00,
2295 'net_amount' => 90.00,
2297 'contribution_status_id' => 1,
2298 'skipCleanMoney' => 1,
2300 'api.contribution.create.1' => array(
2301 'receive_date' => '2011-01-01',
2302 'total_amount' => 120.00,
2303 'financial_type_id' => $this->_financialTypeId
,
2304 'payment_instrument_id' => 1,
2305 'non_deductible_amount' => 10.00,
2306 'fee_amount' => 50.00,
2307 'net_amount' => 90.00,
2309 'contribution_status_id' => 1,
2310 'skipCleanMoney' => 1,
2312 'api.website.create' => array(
2314 'url' => "http://civicrm.org",
2319 $result = $this->callAPISuccess('Contact', 'create', $params);
2321 'id' => $result['id'],
2322 'api.website.getValue' => array('return' => 'url'),
2323 'api.Contribution.getCount' => array(),
2324 'api.CustomValue.get' => 1,
2325 'api.Note.get' => 1,
2326 'api.Membership.getCount' => array(),
2328 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2329 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
2330 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
2331 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
2333 $this->callAPISuccess('contact', 'delete', $result);
2334 $this->customGroupDelete($ids['custom_group_id']);
2335 $this->customGroupDelete($moreIDs['custom_group_id']);
2339 * Test complex chaining.
2341 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
2342 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
2343 $params['custom_' . $ids['custom_field_id']] = "custom string";
2344 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2345 $andMoreIDs = $this->CustomGroupMultipleCreateWithFields(array(
2346 'title' => "another group",
2347 'name' => 'another name',
2349 $description = "This demonstrates the usage of chained api functions with multiple custom fields.";
2350 $subfile = "APIChainedArrayMultipleCustom";
2352 'first_name' => 'abc3',
2353 'last_name' => 'xyz3',
2354 'contact_type' => 'Individual',
2355 'email' => 'man3@yahoo.com',
2356 'api.contribution.create' => array(
2357 'receive_date' => '2010-01-01',
2358 'total_amount' => 100.00,
2359 'financial_type_id' => 1,
2360 'payment_instrument_id' => 1,
2361 'non_deductible_amount' => 10.00,
2362 'fee_amount' => 50.00,
2363 'net_amount' => 90.00,
2365 'invoice_id' => 67890,
2367 'contribution_status_id' => 1,
2368 'skipCleanMoney' => 1,
2370 'api.contribution.create.1' => array(
2371 'receive_date' => '2011-01-01',
2372 'total_amount' => 120.00,
2373 'financial_type_id' => 1,
2374 'payment_instrument_id' => 1,
2375 'non_deductible_amount' => 10.00,
2376 'fee_amount' => 50.00,
2377 'net_amount' => 90.00,
2379 'invoice_id' => 67830,
2381 'contribution_status_id' => 1,
2382 'skipCleanMoney' => 1,
2384 'api.website.create' => array(
2386 'url' => "http://civicrm.org",
2389 'custom_' . $ids['custom_field_id'] => "value 1",
2390 'custom_' . $moreIDs['custom_field_id'][0] => "value 2",
2391 'custom_' . $moreIDs['custom_field_id'][1] => "warm beer",
2392 'custom_' . $andMoreIDs['custom_field_id'][1] => "vegemite",
2395 $result = $this->callAPISuccess('Contact', 'create', $params);
2396 $result = $this->callAPISuccess('Contact', 'create', array(
2397 'contact_type' => 'Individual',
2398 'id' => $result['id'],
2400 $moreIDs['custom_field_id'][0] => "value 3",
2402 $ids['custom_field_id'] => "value 4",
2406 'id' => $result['id'],
2407 'api.website.getValue' => array('return' => 'url'),
2408 'api.Contribution.getCount' => array(),
2409 'api.CustomValue.get' => 1,
2411 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2413 $this->customGroupDelete($ids['custom_group_id']);
2414 $this->customGroupDelete($moreIDs['custom_group_id']);
2415 $this->customGroupDelete($andMoreIDs['custom_group_id']);
2416 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
2417 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
2421 * Test checks usage of $values to pick & choose inputs.
2423 public function testChainingValuesCreate() {
2424 $description = "This demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
2425 2 child functions - one receives values from the parent (Contact) and the other child (Tag).";
2426 $subfile = "APIChainedArrayValuesFromSiblingFunction";
2428 'display_name' => 'batman',
2429 'contact_type' => 'Individual',
2430 'api.tag.create' => array(
2431 'name' => '$value.id',
2432 'description' => '$value.display_name',
2433 'format.only_id' => 1,
2435 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
2437 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2438 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
2440 $tablesToTruncate = array(
2443 'civicrm_entity_tag',
2446 $this->quickCleanup($tablesToTruncate, TRUE);
2450 * Test TrueFalse format - I couldn't come up with an easy way to get an error on Get.
2452 public function testContactGetFormatIsSuccessTrue() {
2453 $this->createContactFromXML();
2454 $description = "This demonstrates use of the 'format.is_success' param.
2455 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2456 $subfile = "FormatIsSuccess_True";
2457 $params = array('id' => 17, 'format.is_success' => 1);
2458 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2459 $this->assertEquals(1, $result);
2460 $this->callAPISuccess('Contact', 'Delete', $params);
2464 * Test TrueFalse format.
2466 public function testContactCreateFormatIsSuccessFalse() {
2468 $description = "This demonstrates use of the 'format.is_success' param.
2469 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2470 $subfile = "FormatIsSuccess_Fail";
2471 $params = array('id' => 500, 'format.is_success' => 1);
2472 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2473 $this->assertEquals(0, $result);
2477 * Test long display names.
2481 public function testContactCreateLongDisplayName() {
2482 $result = $this->callAPISuccess('Contact', 'Create', array(
2483 'first_name' => str_pad('a', 64, 'a'),
2484 'last_name' => str_pad('a', 64, 'a'),
2485 'contact_type' => 'Individual',
2487 $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $result['values'][$result['id']]['display_name']);
2488 $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $result['values'][$result['id']]['sort_name']);
2492 * Test Single Entity format.
2494 public function testContactGetSingleEntityArray() {
2495 $this->createContactFromXML();
2496 $description = "This demonstrates use of the 'format.single_entity_array' param.
2497 This param causes the only contact to be returned as an array without the other levels.
2498 It will be ignored if there is not exactly 1 result";
2499 $subfile = "GetSingleContact";
2500 $params = array('id' => 17);
2501 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2502 $this->assertEquals('Test Contact', $result['display_name']);
2503 $this->callAPISuccess('Contact', 'Delete', $params);
2507 * Test Single Entity format.
2509 public function testContactGetFormatCountOnly() {
2510 $this->createContactFromXML();
2511 $description = "This demonstrates use of the 'getCount' action.
2512 This param causes the count of the only function to be returned as an integer.";
2513 $params = array('id' => 17);
2514 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__
, __FILE__
, $description,
2516 $this->assertEquals('1', $result);
2517 $this->callAPISuccess('Contact', 'Delete', $params);
2521 * Test id only format.
2523 public function testContactGetFormatIDOnly() {
2524 $this->createContactFromXML();
2525 $description = "This demonstrates use of the 'format.id_only' param.
2526 This param causes the id of the only entity to be returned as an integer.
2527 It will be ignored if there is not exactly 1 result";
2528 $subfile = "FormatOnlyID";
2529 $params = array('id' => 17, 'format.only_id' => 1);
2530 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
2531 $this->assertEquals('17', $result);
2532 $this->callAPISuccess('Contact', 'Delete', $params);
2536 * Test id only format.
2538 public function testContactGetFormatSingleValue() {
2539 $this->createContactFromXML();
2540 $description = "This demonstrates use of the 'format.single_value' param.
2541 This param causes only a single value of the only entity to be returned as an string.
2542 It will be ignored if there is not exactly 1 result";
2543 $subFile = "FormatSingleValue";
2544 $params = array('id' => 17, 'return' => 'display_name');
2545 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
2546 $this->assertEquals('Test Contact', $result);
2547 $this->callAPISuccess('Contact', 'Delete', $params);
2551 * Test that permissions are respected when creating contacts.
2553 public function testContactCreationPermissions() {
2555 'contact_type' => 'Individual',
2556 'first_name' => 'Foo',
2557 'last_name' => 'Bear',
2558 'check_permissions' => TRUE,
2560 $config = CRM_Core_Config
::singleton();
2561 $config->userPermissionClass
->permissions
= array('access CiviCRM');
2562 $result = $this->callAPIFailure('contact', 'create', $params);
2563 $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');
2565 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'add contacts', 'import contacts');
2566 $this->callAPISuccess('contact', 'create', $params);
2570 * Test that delete with skip undelete respects permissions.
2572 public function testContactDeletePermissions() {
2573 $contactID = $this->individualCreate();
2574 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
2575 $this->callAPIFailure('Contact', 'delete', array(
2577 'check_permissions' => 1,
2578 'skip_undelete' => 1,
2580 $this->callAPISuccess('Contact', 'delete', array(
2582 'check_permissions' => 0,
2583 'skip_undelete' => 1,
2588 * Test update with check permissions set.
2590 public function testContactUpdatePermissions() {
2592 'contact_type' => 'Individual',
2593 'first_name' => 'Foo',
2594 'last_name' => 'Bear',
2595 'check_permissions' => TRUE,
2597 $result = $this->callAPISuccess('contact', 'create', $params);
2598 $config = CRM_Core_Config
::singleton();
2600 'id' => $result['id'],
2601 'contact_type' => 'Individual',
2602 'last_name' => 'Bar',
2603 'check_permissions' => TRUE,
2606 $config->userPermissionClass
->permissions
= array('access CiviCRM');
2607 $result = $this->callAPIFailure('contact', 'update', $params);
2608 $this->assertEquals('Permission denied to modify contact record', $result['error_message']);
2610 $config->userPermissionClass
->permissions
= array(
2613 'view all contacts',
2614 'edit all contacts',
2617 $this->callAPISuccess('contact', 'update', $params);
2621 * Set up helper to create a contact.
2623 public function createContactFromXML() {
2624 // Insert a row in civicrm_contact creating contact 17.
2625 $op = new PHPUnit_Extensions_Database_Operation_Insert();
2626 $op->execute($this->_dbconn
,
2627 $this->createXMLDataSet(
2628 dirname(__FILE__
) . '/dataset/contact_17.xml'
2634 * Test contact proximity api.
2636 public function testContactProximity() {
2637 // first create a contact with a SF location with a specific
2639 $contactID = $this->organizationCreate();
2641 // now create the address
2643 'street_address' => '123 Main Street',
2644 'city' => 'San Francisco',
2646 'country_id' => 1228,
2647 'state_province_id' => 1004,
2648 'geo_code_1' => '37.79',
2649 'geo_code_2' => '-122.40',
2650 'location_type_id' => 1,
2651 'contact_id' => $contactID,
2654 $result = $this->callAPISuccess('address', 'create', $params);
2655 $this->assertEquals(1, $result['count']);
2657 // now do a proximity search with a close enough geocode and hope to match
2658 // that specific contact only!
2659 $proxParams = array(
2661 'longitude' => -122.3,
2665 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
2666 $this->assertEquals(1, $result['count']);
2670 * Test that Ajax API permission is sufficient to access getquick api.
2672 * (note that getquick api is required for autocomplete & has ACL permissions applied)
2674 public function testGetquickPermissionCRM13744() {
2675 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviEvent');
2676 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2677 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
2678 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2679 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access AJAX API');
2680 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2684 * Test that getquick returns contacts with an exact first name match first.
2686 * The search string 'b' & 'bob' both return ordered by sort_name if includeOrderByClause
2687 * is true (default) but if it is false then matches are returned in ID order.
2689 * @dataProvider getSearchSortOptions
2691 public function testGetQuickExactFirst($searchParameters, $settings, $firstContact, $secondContact = NULL) {
2692 $this->getQuickSearchSampleData();
2693 $this->callAPISuccess('Setting', 'create', $settings);
2694 $result = $this->callAPISuccess('contact', 'getquick', $searchParameters);
2695 $this->assertEquals($firstContact, $result['values'][0]['sort_name']);
2696 $this->assertEquals($secondContact, $result['values'][1]['sort_name']);
2697 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE));
2700 public function getSearchSortOptions() {
2701 $firstAlphabeticalContactBySortName = 'A Bobby, Bobby';
2702 $secondAlphabeticalContactBySortName = 'Aadvark, Bob';
2703 $secondAlphabeticalContactWithEmailBySortName = 'Bob, Bob';
2704 $firstAlphabeticalContactFirstNameBob = 'Aadvark, Bob';
2705 $secondAlphabeticalContactFirstNameBob = 'Bob, Bob';
2706 $firstByIDContactFirstNameBob = 'Bob, Bob';
2707 $secondByIDContactFirstNameBob = 'K Bobby, Bob';
2708 $firstContactByID = 'Bob, Bob';
2709 $secondContactByID = 'E Bobby, Bobby';
2710 $bobLikeEmail = 'A Bobby, Bobby';
2713 'empty_search_basic' => array(
2714 'search_parameters' => array('name' => '%'),
2715 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2716 'first_contact' => $firstAlphabeticalContactBySortName,
2717 'second_contact' => $secondAlphabeticalContactBySortName,
2719 'empty_search_basic_no_wildcard' => array(
2720 'search_parameters' => array('name' => '%'),
2721 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2722 'first_contact' => $firstAlphabeticalContactBySortName,
2723 'second_contact' => $secondAlphabeticalContactBySortName,
2725 'single_letter_search_basic' => array(
2726 'search_parameters' => array('name' => 'b'),
2727 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2728 'first_contact' => $firstAlphabeticalContactBySortName,
2729 'second_contact' => $secondAlphabeticalContactBySortName,
2731 'bob_search_basic' => array(
2732 'search_parameters' => array('name' => 'bob'),
2733 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2734 'first_contact' => $firstAlphabeticalContactBySortName,
2735 'second_contact' => $secondAlphabeticalContactBySortName,
2737 // This test has been disabled as is proving to be problematic to reproduce due to MySQL sorting issues between different versions
2738 // 'bob_search_no_orderby' => array(
2739 // 'search_parameters' => array('name' => 'bob'),
2740 // 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => FALSE),
2741 // 'first_contact' => $firstContactByID,
2742 // 'second_contact' => $secondContactByID,
2744 'bob_search_no_wildcard' => array(
2745 'search_parameters' => array('name' => 'bob'),
2746 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2747 'second_contact' => $bobLikeEmail,
2748 'first_contact' => $secondAlphabeticalContactFirstNameBob,
2750 // This should be the same as just no wildcard as if we had an exactMatch while searching by
2751 // sort name it would rise to the top CRM-19547
2752 'bob_search_no_wildcard_no_orderby' => array(
2753 'search_parameters' => array('name' => 'bob'),
2754 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2755 'second_contact' => $bobLikeEmail,
2756 'first_contact' => $secondAlphabeticalContactFirstNameBob,
2758 'first_name_search_basic' => array(
2759 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2760 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2761 'first_contact' => $firstAlphabeticalContactFirstNameBob,
2762 'second_contact' => $secondAlphabeticalContactFirstNameBob,
2764 'first_name_search_no_wildcard' => array(
2765 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2766 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2767 'first_contact' => $firstAlphabeticalContactFirstNameBob,
2768 'second_contact' => $secondAlphabeticalContactFirstNameBob,
2770 // This test has been disabled as is proving to be problematic to reproduce due to MySQL sorting issues between different versions
2771 //'first_name_search_no_orderby' => array(
2772 // 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2773 // 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => FALSE),
2774 // 'first_contact' => $firstByIDContactFirstNameBob,
2775 // 'second_contact' => $secondByIDContactFirstNameBob,
2777 'email_search_basic' => array(
2778 'search_parameters' => array('name' => 'bob', 'field_name' => 'email', 'table_name' => 'eml'),
2779 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2780 'first_contact' => $firstAlphabeticalContactBySortName,
2781 'second_contact' => $secondAlphabeticalContactWithEmailBySortName,
2787 * Test that getquick returns contacts with an exact first name match first.
2789 public function testGetQuickEmail() {
2790 $this->getQuickSearchSampleData();
2791 $loggedInContactID = $this->createLoggedInUser();
2792 $result = $this->callAPISuccess('contact', 'getquick', array(
2795 $expectedData = array(
2796 'A Bobby, Bobby :: bob@bobby.com',
2797 'Bob, Bob :: bob@bob.com',
2799 'H Bobby, Bobby :: bob@h.com',
2801 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
2803 $this->assertEquals(6, $result['count']);
2804 foreach ($expectedData as $index => $value) {
2805 $this->assertEquals($value, $result['values'][$index]['data']);
2807 $result = $this->callAPISuccess('contact', 'getquick', array(
2810 $expectedData = array(
2811 'H Bobby, Bobby :: bob@h.com',
2813 foreach ($expectedData as $index => $value) {
2814 $this->assertEquals($value, $result['values'][$index]['data']);
2816 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => FALSE));
2817 $result = $this->callAPISuccess('contact', 'getquick', array(
2820 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE));
2821 $this->assertEquals(0, $result['count']);
2825 * Test that getquick returns contacts with an exact first name match first.
2827 public function testGetQuickEmailACL() {
2828 $this->getQuickSearchSampleData();
2829 $loggedInContactID = $this->createLoggedInUser();
2830 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array();
2831 $result = $this->callAPISuccess('contact', 'getquick', array(
2834 $this->assertEquals(0, $result['count']);
2836 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
2837 CRM_Contact_BAO_Contact_Permission
::cache($loggedInContactID, CRM_Core_Permission
::VIEW
, TRUE);
2838 $result = $this->callAPISuccess('contact', 'getquick', array(
2842 // Without the acl it would be 6 like the previous email getquick test.
2843 $this->assertEquals(5, $result['count']);
2844 $expectedData = array(
2845 'A Bobby, Bobby :: bob@bobby.com',
2846 'Bob, Bob :: bob@bob.com',
2849 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
2851 foreach ($expectedData as $index => $value) {
2852 $this->assertEquals($value, $result['values'][$index]['data']);
2857 * Test that getquick returns contacts with an exact first name match first.
2859 public function testGetQuickExternalID() {
2860 $this->getQuickSearchSampleData();
2861 $result = $this->callAPISuccess('contact', 'getquick', array(
2863 'field_name' => 'external_identifier',
2864 'table_name' => 'cc',
2866 $this->assertEquals(0, $result['count']);
2867 $result = $this->callAPISuccess('contact', 'getquick', array(
2869 'field_name' => 'external_identifier',
2870 'table_name' => 'cc',
2872 $this->assertEquals(1, $result['count']);
2873 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2877 * Test that getquick returns contacts with an exact first name match first.
2879 public function testGetQuickID() {
2880 $max = CRM_Core_DAO
::singleValueQuery("SELECT max(id) FROM civicrm_contact");
2881 $this->getQuickSearchSampleData();
2882 $result = $this->callAPISuccess('contact', 'getquick', array(
2884 'field_name' => 'id',
2885 'table_name' => 'cc',
2887 $this->assertEquals(1, $result['count']);
2888 $this->assertEquals('E Bobby, Bobby', $result['values'][0]['sort_name']);
2889 $result = $this->callAPISuccess('contact', 'getquick', array(
2891 'field_name' => 'contact_id',
2892 'table_name' => 'cc',
2894 $this->assertEquals(1, $result['count']);
2895 $this->assertEquals('E Bobby, Bobby', $result['values'][0]['sort_name']);
2899 * Test that getquick returns contacts with an exact first name match first.
2901 * Depending on the setting the sort name sort might click in next or not - test!
2903 public function testGetQuickFirstName() {
2904 $this->getQuickSearchSampleData();
2905 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2906 $result = $this->callAPISuccess('contact', 'getquick', array(
2908 'field_name' => 'first_name',
2909 'table_name' => 'cc',
2918 foreach ($expected as $index => $value) {
2919 $this->assertEquals($value, $result['values'][$index]['sort_name']);
2921 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
2922 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2923 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2924 // This test has been disabled as is proving to be problematic to reproduce due to MySQL sorting issues between different versions
2925 //$this->assertEquals('E Bobby, Bobby', $result['values'][1]['sort_name']);
2929 * Test that getquick applies ACLs.
2931 public function testGetQuickFirstNameACLs() {
2932 $this->getQuickSearchSampleData();
2933 $userID = $this->createLoggedInUser();
2934 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE, 'search_autocomplete_count' => 15));
2935 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array();
2936 $result = $this->callAPISuccess('contact', 'getquick', array(
2938 'field_name' => 'first_name',
2939 'table_name' => 'cc',
2941 $this->assertEquals(0, $result['count']);
2943 $this->hookClass
->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
2944 CRM_Contact_BAO_Contact_Permission
::cache($userID, CRM_Core_Permission
::VIEW
, TRUE);
2945 $result = $this->callAPISuccess('contact', 'getquick', array(
2947 'field_name' => 'first_name',
2948 'table_name' => 'cc',
2950 $this->assertEquals('K Bobby, Bob', $result['values'][2]['sort_name']);
2951 // Without the ACL 9 would be bob@h.com.
2952 $this->assertEquals('I Bobby, Bobby', $result['values'][10]['sort_name']);
2956 * Full results returned.
2957 * @implements CRM_Utils_Hook::aclWhereClause
2959 * @param string $type
2960 * @param array $tables
2961 * @param array $whereTables
2962 * @param int $contactID
2963 * @param string $where
2965 public function aclWhereNoBobH($type, &$tables, &$whereTables, &$contactID, &$where) {
2966 $where = " (email <> 'bob@h.com' OR email IS NULL) ";
2967 $whereTables['civicrm_email'] = "LEFT JOIN civicrm_email e ON contact_a.id = e.contact_id";
2971 * Test that getquick returns contacts with an exact last name match first.
2973 public function testGetQuickLastName() {
2974 $this->getQuickSearchSampleData();
2975 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2976 $result = $this->callAPISuccess('contact', 'getquick', array(
2978 'field_name' => 'last_name',
2979 'table_name' => 'cc',
2987 foreach ($expected as $index => $value) {
2988 $this->assertEquals($value, $result['values'][$index]['sort_name']);
2990 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
2991 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2992 $this->assertEquals('Bob, Bob :: bob@bob.com', $result['values'][0]['data']);
2996 * Test that getquick returns contacts by city.
2998 public function testGetQuickCity() {
2999 $this->getQuickSearchSampleData();
3000 $result = $this->callAPISuccess('contact', 'getquick', array(
3002 'field_name' => 'city',
3003 'table_name' => 'sts',
3005 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
3006 $result = $this->callAPISuccess('contact', 'getquick', array(
3008 'field_name' => 'city',
3009 'table_name' => 'sts',
3011 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
3012 $this->assertEquals('C Bobby, Bobby :: Whanganui', $result['values'][1]['data']);
3016 * Set up some sample data for testing quicksearch.
3018 public function getQuickSearchSampleData() {
3020 array('first_name' => 'Bob', 'last_name' => 'Bob', 'external_identifier' => 'abc', 'email' => 'bob@bob.com'),
3021 array('first_name' => 'Bobby', 'last_name' => 'E Bobby', 'external_identifier' => 'abcd'),
3023 'first_name' => 'Bobby',
3024 'last_name' => 'B Bobby',
3025 'external_identifier' => 'bcd',
3026 'api.address.create' => array(
3027 'street_address' => 'Sesame Street',
3028 'city' => 'Toronto',
3029 'location_type_id' => 1,
3033 'first_name' => 'Bobby',
3034 'last_name' => 'C Bobby',
3035 'external_identifier' => 'bcde',
3036 'api.address.create' => array(
3037 'street_address' => 'Te huarahi',
3038 'city' => 'Whanganui',
3039 'location_type_id' => 1,
3042 array('first_name' => 'Bobby', 'last_name' => 'D Bobby', 'external_identifier' => 'efg'),
3043 array('first_name' => 'Bobby', 'last_name' => 'A Bobby', 'external_identifier' => 'hij', 'email' => 'bob@bobby.com'),
3044 array('first_name' => 'Bobby', 'last_name' => 'F Bobby', 'external_identifier' => 'klm'),
3045 array('first_name' => 'Bobby', 'last_name' => 'G Bobby', 'external_identifier' => 'nop'),
3046 array('first_name' => 'Bobby', 'last_name' => 'H Bobby', 'external_identifier' => 'qrs', 'email' => 'bob@h.com'),
3047 array('first_name' => 'Bobby', 'last_name' => 'I Bobby'),
3048 array('first_name' => 'Bobby', 'last_name' => 'J Bobby'),
3049 array('first_name' => 'Bob', 'last_name' => 'K Bobby', 'external_identifier' => 'bcdef'),
3050 array('first_name' => 'Bob', 'last_name' => 'Aadvark'),
3052 foreach ($contacts as $type => $contact) {
3053 $contact['contact_type'] = 'Individual';
3054 $this->callAPISuccess('Contact', 'create', $contact);
3059 * Test get ref api - gets a list of references to an entity.
3061 public function testGetReferenceCounts() {
3062 $result = $this->callAPISuccess('Contact', 'create', array(
3063 'first_name' => 'Testily',
3064 'last_name' => 'McHaste',
3065 'contact_type' => 'Individual',
3066 'api.Address.replace' => array(
3067 'values' => array(),
3069 'api.Email.replace' => array(
3072 'email' => 'spam@dev.null',
3074 'location_type_id' => 1,
3078 'api.Phone.replace' => array(
3081 'phone' => '234-567-0001',
3083 'location_type_id' => 1,
3086 'phone' => '234-567-0002',
3088 'location_type_id' => 1,
3094 //$dao = new CRM_Contact_BAO_Contact();
3095 //$dao->id = $result['id'];
3096 //$this->assertTrue((bool) $dao->find(TRUE));
3098 //$refCounts = $dao->getReferenceCounts();
3099 //$this->assertTrue(is_array($refCounts));
3100 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
3102 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
3103 'id' => $result['id'],
3105 $refCountsIdx = CRM_Utils_Array
::index(array('name'), $refCounts['values']);
3107 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
3108 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
3109 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
3110 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
3111 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
3115 * Test the use of sql operators.
3117 public function testSQLOperatorsOnContactAPI() {
3118 $this->individualCreate();
3119 $this->organizationCreate();
3120 $this->householdCreate();
3121 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
3122 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
3123 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
3124 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
3128 * CRM-14743 - test api respects search operators.
3130 public function testGetModifiedDateByOperators() {
3131 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
3132 $contact1 = $this->individualCreate();
3133 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
3134 CRM_Core_DAO
::executeQuery($sql);
3135 $contact2 = $this->individualCreate();
3136 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
3137 CRM_Core_DAO
::executeQuery($sql);
3138 $contact3 = $this->householdCreate();
3139 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
3140 CRM_Core_DAO
::executeQuery($sql);
3141 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
3142 $this->assertEquals($contacts['count'], 3);
3143 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
3144 $this->assertEquals($contacts['count'], $preExistingContactCount);
3148 * CRM-14743 - test api respects search operators.
3150 public function testGetCreatedDateByOperators() {
3151 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
3152 $contact1 = $this->individualCreate();
3153 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
3154 CRM_Core_DAO
::executeQuery($sql);
3155 $contact2 = $this->individualCreate();
3156 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
3157 CRM_Core_DAO
::executeQuery($sql);
3158 $contact3 = $this->householdCreate();
3159 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
3160 CRM_Core_DAO
::executeQuery($sql);
3161 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
3162 $this->assertEquals($contacts['count'], 3);
3163 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
3164 $this->assertEquals($contacts['count'], $preExistingContactCount);
3168 * CRM-14263 check that API is not affected by search profile related bug.
3170 public function testReturnCityProfile() {
3171 $contactID = $this->individualCreate();
3172 CRM_Core_Config
::singleton()->defaultSearchProfileID
= 1;
3173 $this->callAPISuccess('address', 'create', array(
3174 'contact_id' => $contactID,
3175 'city' => 'Cool City',
3176 'location_type_id' => 1,
3178 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
3179 $this->assertEquals(1, $result['count']);
3183 * CRM-15443 - ensure getlist api does not return deleted contacts.
3185 public function testGetlistExcludeConditions() {
3186 $name = md5(time());
3187 $contact = $this->individualCreate(array('last_name' => $name));
3188 $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
3189 $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
3190 // We should get all but the deleted contact.
3191 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
3192 $this->assertEquals(2, $result['count']);
3193 // Force-exclude the deceased contact.
3194 $result = $this->callAPISuccess('contact', 'getlist', array(
3196 'params' => array('is_deceased' => 0),
3198 $this->assertEquals(1, $result['count']);
3199 $this->assertEquals($contact, $result['values'][0]['id']);
3203 * Test contact getactions.
3205 public function testGetActions() {
3206 $description = "Getting the available actions for an entity.";
3207 $result = $this->callAPIAndDocument($this->_entity
, 'getactions', array(), __FUNCTION__
, __FILE__
, $description);
3227 $deprecated = array(
3231 foreach ($expected as $action) {
3232 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
3234 foreach ($deprecated as $action) {
3235 $this->assertArrayKeyExists($action, $result['deprecated']);
3240 * Test the duplicate check function.
3242 public function testDuplicateCheck() {
3244 'first_name' => 'Harry',
3245 'last_name' => 'Potter',
3246 'email' => 'harry@hogwarts.edu',
3247 'contact_type' => 'Individual',
3249 $this->callAPISuccess('Contact', 'create', $harry);
3250 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3254 $this->assertEquals(1, $result['count']);
3255 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3257 'first_name' => 'Harry',
3258 'last_name' => 'Potter',
3259 'email' => 'no5@privet.drive',
3260 'contact_type' => 'Individual',
3263 $this->assertEquals(0, $result['count']);
3264 $this->callAPIFailure('Contact', 'create', array_merge($harry, array('dupe_check' => 1)));
3268 * Test the duplicate check function.
3270 public function testDuplicateCheckRuleNotReserved() {
3272 'first_name' => 'Harry',
3273 'last_name' => 'Potter',
3274 'email' => 'harry@hogwarts.edu',
3275 'contact_type' => 'Individual',
3277 $defaultRule = $this->callAPISuccess('RuleGroup', 'getsingle', array('used' => 'Unsupervised', 'is_reserved' => 1));
3278 $this->callAPISuccess('RuleGroup', 'create', array('id' => $defaultRule['id'], 'is_reserved' => 0));
3279 $this->callAPISuccess('Contact', 'create', $harry);
3280 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3284 $this->assertEquals(1, $result['count']);
3285 $this->callAPISuccess('RuleGroup', 'create', array('id' => $defaultRule['id'], 'is_reserved' => 1));
3289 * Test variants on retrieving contact by type.
3291 public function testGetByContactType() {
3292 $individual = $this->callAPISuccess('Contact', 'create', array(
3293 'email' => 'individual@test.com',
3294 'contact_type' => 'Individual',
3296 $household = $this->callAPISuccess('Contact', 'create', array(
3297 'household_name' => 'household@test.com',
3298 'contact_type' => 'Household',
3300 $organization = $this->callAPISuccess('Contact', 'create', array(
3301 'organization_name' => 'organization@test.com',
3302 'contact_type' => 'Organization',
3304 // Test with id - getsingle will throw an exception if not found
3305 $this->callAPISuccess('Contact', 'getsingle', array(
3306 'id' => $individual['id'],
3307 'contact_type' => 'Individual',
3309 $this->callAPISuccess('Contact', 'getsingle', array(
3310 'id' => $individual['id'],
3311 'contact_type' => array('IN' => array('Individual')),
3314 $this->callAPISuccess('Contact', 'getsingle', array(
3315 'id' => $organization['id'],
3316 'contact_type' => array('IN' => array('Individual', 'Organization')),
3319 $result = $this->callAPISuccess('Contact', 'get', array(
3320 'contact_type' => array('IN' => array('Individual', 'Organization')),
3321 'options' => array('limit' => 0),
3324 $this->assertContains($organization['id'], array_keys($result['values']));
3325 $this->assertContains($individual['id'], array_keys($result['values']));
3326 $this->assertNotContains($household['id'], array_keys($result['values']));
3328 $result = $this->callAPISuccess('Contact', 'get', array(
3329 'contact_type' => 'Household',
3330 'options' => array('limit' => 0),
3333 $this->assertNotContains($organization['id'], array_keys($result['values']));
3334 $this->assertNotContains($individual['id'], array_keys($result['values']));
3335 $this->assertContains($household['id'], array_keys($result['values']));
3339 * Test merging 2 contacts.
3341 * Someone kindly bequethed us the legacy of mixed up use of main_id & other_id
3342 * in the params for contact.merge api.
3344 * This test protects that legacy.
3346 public function testMergeBizzareOldParams() {
3347 $this->createLoggedInUser();
3348 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3349 $mainContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3350 $this->callAPISuccess('contact', 'merge', array(
3351 'main_id' => $mainContact['id'],
3352 'other_id' => $otherContact['id'],
3354 $contacts = $this->callAPISuccess('contact', 'get', $this->_params
);
3355 $this->assertEquals($otherContact['id'], $contacts['id']);
3359 * Test merging 2 contacts.
3361 public function testMerge() {
3362 $this->createLoggedInUser();
3363 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3364 $retainedContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3365 $this->callAPISuccess('contact', 'merge', array(
3366 'to_keep_id' => $retainedContact['id'],
3367 'to_remove_id' => $otherContact['id'],
3368 'auto_flip' => FALSE,
3371 $contacts = $this->callAPISuccess('contact', 'get', $this->_params
);
3372 $this->assertEquals($retainedContact['id'], $contacts['id']);
3373 $activity = $this->callAPISuccess('Activity', 'getsingle', array(
3374 'target_contact_id' => $retainedContact['id'],
3375 'activity_type_id' => 'Contact Merged',
3377 $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($activity['activity_date_time'])));
3378 $activity2 = $this->callAPISuccess('Activity', 'getsingle', array(
3379 'target_contact_id' => $otherContact['id'],
3380 'activity_type_id' => 'Contact Deleted by Merge',
3382 $this->assertEquals($activity['id'], $activity2['parent_id']);
3383 $this->assertEquals('Normal', civicrm_api3('option_value', 'getvalue', array(
3384 'value' => $activity['priority_id'],
3385 'return' => 'label',
3386 'option_group_id' => 'priority',
3392 * Test merging 2 contacts with delete to trash off.
3394 * We are checking that there is no error due to attempting to add an activity for the
3399 public function testMergeNoTrash() {
3400 $this->createLoggedInUser();
3401 $this->callAPISuccess('Setting', 'create', array('contact_undelete' => FALSE));
3402 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3403 $retainedContact = $this->callAPISuccess('contact', 'create', $this->_params
);
3404 $this->callAPISuccess('contact', 'merge', array(
3405 'to_keep_id' => $retainedContact['id'],
3406 'to_remove_id' => $otherContact['id'],
3407 'auto_flip' => FALSE,
3409 $this->callAPISuccess('Setting', 'create', array('contact_undelete' => TRUE));
3413 * Ensure format with return=group shows comma-separated group IDs.
3417 public function testContactGetReturnGroup() {
3418 // Set up a contact, asser that they were created.
3419 $contact_params = array(
3420 'contact_type' => 'Individual',
3421 'first_name' => 'Test',
3422 'last_name' => 'Groupmember',
3423 'email' => 'test@example.org',
3425 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3426 $this->assertEquals(0, $create_contact['is_error']);
3427 $this->assertInternalType('int', $create_contact['id']);
3429 $created_contact_id = $create_contact['id'];
3431 // Set up multiple groups, add the contact to the groups.
3432 $test_groups = array('Test group A', 'Test group B');
3433 foreach ($test_groups as $title) {
3434 // Use this contact as group owner, since we know they exist.
3435 $group_params = array(
3437 'created_id' => $created_contact_id,
3439 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3440 $this->assertEquals(0, $create_group['is_error']);
3441 $this->assertInternalType('int', $create_group['id']);
3443 $created_group_ids[] = $create_group['id'];
3445 // Add contact to the new group.
3446 $group_contact_params = array(
3447 'contact_id' => $created_contact_id,
3448 'group_id' => $create_group['id'],
3450 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3451 $this->assertEquals(0, $create_group_contact['is_error']);
3452 $this->assertInternalType('int', $create_group_contact['added']);
3455 // Use the Contact,get API to retrieve the contact
3456 $contact_get_params = array(
3457 'id' => $created_contact_id,
3458 'return' => 'group',
3460 $contact_get = $this->callApiSuccess('Contact', 'get', $contact_get_params);
3461 $this->assertInternalType('array', $contact_get['values'][$created_contact_id]);
3462 $this->assertInternalType('string', $contact_get['values'][$created_contact_id]['groups']);
3464 // Ensure they are shown as being in each created group.
3465 $contact_group_ids = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3466 foreach ($created_group_ids as $created_group_id) {
3467 $this->assertContains($created_group_id, $contact_group_ids);
3472 * CRM-20144 Verify that passing title of group works as well as id
3473 * Tests the following formats
3474 * contact.get group='title1'
3475 * contact.get group=id1
3477 public function testContactGetWithGroupTitle() {
3478 // Set up a contact, asser that they were created.
3479 $contact_params = array(
3480 'contact_type' => 'Individual',
3481 'first_name' => 'Test2',
3482 'last_name' => 'Groupmember',
3483 'email' => 'test@example.org',
3485 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3486 $created_contact_id = $create_contact['id'];
3487 // Set up multiple groups, add the contact to the groups.
3488 $test_groups = array('Test group C', 'Test group D');
3489 foreach ($test_groups as $title) {
3490 $group_params = array(
3492 'created_id' => $created_contact_id,
3494 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3495 $created_group_id = $create_group['id'];
3497 // Add contact to the new group.
3498 $group_contact_params = array(
3499 'contact_id' => $created_contact_id,
3500 'group_id' => $create_group['id'],
3502 $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3503 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => $title, 'return' => 'group'));
3504 $this->assertEquals(1, $contact_get['count']);
3505 $this->assertEquals($created_contact_id, $contact_get['id']);
3506 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3507 $this->assertContains((string) $create_group['id'], $contact_groups);
3508 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => $created_group_id, 'return' => 'group'));
3509 $this->assertEquals($created_contact_id, $contact_get2['id']);
3510 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3511 $this->assertContains((string) $create_group['id'], $contact_groups2);
3512 $this->callAPISuccess('group', 'delete', array('id' => $created_group_id));
3514 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3518 * CRM-20144 Verify that passing title of group works as well as id
3519 * Tests the following formats
3520 * contact.get group=array('title1', title1)
3521 * contact.get group=array('IN' => array('title1', 'title2)
3523 public function testContactGetWithGroupTitleMultipleGroups() {
3524 $description = "Get all from group and display contacts.";
3525 $subFile = "GroupFilterUsingContactAPI";
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 $createdGroupsTitles = $createdGroupsIds = array();
3536 // Set up multiple groups, add the contact to the groups.
3537 $test_groups = array('Test group C', 'Test group D');
3538 foreach ($test_groups as $title) {
3539 $group_params = array(
3541 'created_id' => $created_contact_id,
3543 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3544 $created_group_id = $create_group['id'];
3545 $createdGroupsIds[] = $create_group['id'];
3546 $createdGroupTitles[] = $title;
3547 // Add contact to the new group.
3548 $group_contact_params = array(
3549 'contact_id' => $created_contact_id,
3550 'group_id' => $create_group['id'],
3552 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3554 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => $createdGroupTitles, 'return' => 'group'));
3555 $this->assertEquals(1, $contact_get['count']);
3556 $this->assertEquals($created_contact_id, $contact_get['id']);
3557 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3558 foreach ($createdGroupsIds as $id) {
3559 $this->assertContains((string) $id, $contact_groups);
3561 $contact_get2 = $this->callAPIAndDocument('contact', 'get', array('group' => array('IN' => $createdGroupTitles)), __FUNCTION__
, __FILE__
, $description, $subFile);
3562 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => array('IN' => $createdGroupTitles), 'return' => 'group'));
3563 $this->assertEquals($created_contact_id, $contact_get2['id']);
3564 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3565 foreach ($createdGroupsIds as $id) {
3566 $this->assertContains((string) $id, $contact_groups2);
3568 foreach ($createdGroupsIds as $id) {
3569 $this->callAPISuccess('group', 'delete', array('id' => $id));
3571 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3575 * CRM-20144 Verify that passing title of group works as well as id
3576 * Tests the following formats
3577 * contact.get group=array('title1' => 1)
3578 * contact.get group=array('titke1' => 1, 'title2' => 1)
3579 * contact.get group=array('id1' => 1)
3580 * contact.get group=array('id1' => 1, id2 => 1)
3582 public function testContactGetWithGroupTitleMultipleGroupsLegacyFormat() {
3583 // Set up a contact, asser that they were created.
3584 $contact_params = array(
3585 'contact_type' => 'Individual',
3586 'first_name' => 'Test2',
3587 'last_name' => 'Groupmember',
3588 'email' => 'test@example.org',
3590 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3591 $created_contact_id = $create_contact['id'];
3592 $createdGroupsTitles = $createdGroupsIds = array();
3593 // Set up multiple groups, add the contact to the groups.
3594 $test_groups = array('Test group C', 'Test group D');
3595 foreach ($test_groups as $title) {
3596 $group_params = array(
3598 'created_id' => $created_contact_id,
3600 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3601 $created_group_id = $create_group['id'];
3602 $createdGroupsIds[] = $create_group['id'];
3603 $createdGroupTitles[] = $title;
3604 // Add contact to the new group.
3605 $group_contact_params = array(
3606 'contact_id' => $created_contact_id,
3607 'group_id' => $create_group['id'],
3609 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3611 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupTitles[0] => 1), 'return' => 'group'));
3612 $this->assertEquals(1, $contact_get['count']);
3613 $this->assertEquals($created_contact_id, $contact_get['id']);
3614 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3615 foreach ($createdGroupsIds as $id) {
3616 $this->assertContains((string) $id, $contact_groups);
3618 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupTitles[0] => 1, $createdGroupTitles[1] => 1), 'return' => 'group'));
3619 $this->assertEquals(1, $contact_get2['count']);
3620 $this->assertEquals($created_contact_id, $contact_get2['id']);
3621 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3622 foreach ($createdGroupsIds as $id) {
3623 $this->assertContains((string) $id, $contact_groups2);
3625 $contact_get3 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupsIds[0] => 1), 'return' => 'group'));
3626 $this->assertEquals($created_contact_id, $contact_get3['id']);
3627 $contact_groups3 = explode(',', $contact_get3['values'][$created_contact_id]['groups']);
3628 foreach ($createdGroupsIds as $id) {
3629 $this->assertContains((string) $id, $contact_groups3);
3631 $contact_get4 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupsIds[0] => 1, $createdGroupsIds[1] => 1), 'return' => 'group'));
3632 $this->assertEquals($created_contact_id, $contact_get4['id']);
3633 $contact_groups4 = explode(',', $contact_get4['values'][$created_contact_id]['groups']);
3634 foreach ($createdGroupsIds as $id) {
3635 $this->assertContains((string) $id, $contact_groups4);
3637 foreach ($createdGroupsIds as $id) {
3638 $this->callAPISuccess('group', 'delete', array('id' => $id));
3640 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3644 * Test the prox_distance functionality works.
3646 * This is primarily testing functionality in the BAO_Query object that 'happens to be'
3647 * accessible via the api.
3649 public function testContactGetProximity() {
3650 CRM_Core_Config
::singleton()->geocodeMethod
= 'CRM_Utils_MockGeocoder';
3651 $this->individualCreate();
3652 $contactID = $this->individualCreate();
3653 $this->callAPISuccess('Address', 'create', [
3654 'contact_id' => $contactID,
3656 'city' => 'Whangarei',
3657 'street_address' => 'Dent St',
3658 'geo_code_1' => '-35.8743325',
3659 'geo_code_2' => '174.4567136',
3660 'location_type_id' => 'Home',
3662 $contact = $this->callAPISuccess('Contact', 'get', [
3663 'prox_distance' => 100,
3664 'prox_geo_code_1' => '-35.72192',
3665 'prox_geo_code_2' => '174.32034',
3667 $this->assertEquals(1, $contact['count']);
3668 $this->assertEquals($contactID, $contact['id']);
3671 public function testLoggedInUserAPISupportToken() {
3672 $description = "Get contact id of the current logged in user";
3673 $subFile = "ContactIDOfLoggedInUserContactAPI";
3674 $cid = $this->createLoggedInUser();
3675 $contact = $this->callAPIAndDocument('contact', 'get', array('id' => 'user_contact_id'), __FUNCTION__
, __FILE__
, $description, $subFile);
3676 $this->assertEquals($cid, $contact['id']);
3683 protected function putGroupContactCacheInClearableState($groupID, $contact) {
3684 // We need to force the situation where there is invalid data in the cache and it
3685 // is due to be cleared.
3686 CRM_Core_DAO
::executeQuery("
3687 INSERT INTO civicrm_group_contact_cache (group_id, contact_id)
3688 VALUES ({$groupID}, {$contact['id']})
3690 CRM_Core_DAO
::executeQuery("UPDATE civicrm_group SET cache_date = '2017-01-01'");
3691 // Reset so it does not skip.
3692 Civi
::$statics['CRM_Contact_BAO_GroupContactCache']['is_refresh_init'] = FALSE;
3696 * CRM-21041 Test if 'communication style' is set to site default if not passed.
3698 public function testCreateCommunicationStyleUnset() {
3699 $this->callAPISuccess('Contact', 'create', array(
3700 'first_name' => 'John',
3701 'last_name' => 'Doe',
3702 'contact_type' => 'Individual')
3704 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Doe'));
3705 $this->assertEquals(1, $result['communication_style_id']);
3709 * CRM-21041 Test if 'communication style' is set if value is passed.
3711 public function testCreateCommunicationStylePassed() {
3712 $this->callAPISuccess('Contact', 'create', array(
3713 'first_name' => 'John',
3714 'last_name' => 'Doe',
3715 'contact_type' => 'Individual',
3716 'communication_style_id' => 'Familiar',
3718 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Doe'));
3720 'option_group_id' => 'communication_style',
3721 'label' => 'Familiar',
3722 'return' => 'value',
3724 $optionResult = civicrm_api3('OptionValue', 'get', $params);
3725 $communicationStyle = reset($optionResult['values']);
3726 $this->assertEquals($communicationStyle['value'], $result['communication_style_id']);
3730 * Test that creating a contact with various contact greetings works.
3732 public function testContactGreetingsCreate() {
3733 $contact = $this->callAPISuccess('Contact', 'create', array('first_name' => 'Alan', 'last_name' => 'MouseMouse', 'contact_type' => 'Individual'));
3734 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3735 $this->assertEquals('Dear Alan', $contact['postal_greeting_display']);
3737 $contact = $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'postal_greeting_id' => 2));
3738 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3739 $this->assertEquals('Dear Alan MouseMouse', $contact['postal_greeting_display']);
3741 $contact = $this->callAPISuccess('Contact', 'create', array('organization_name' => 'Alan\'s Show', 'contact_type' => 'Organization'));
3742 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting, addressee, email_greeting'));
3743 $this->assertEquals('', $contact['postal_greeting_display']);
3744 $this->assertEquals('', $contact['email_greeting_display']);
3745 $this->assertEquals('Alan\'s Show', $contact['addressee_display']);
3749 * Test that creating a contact with various contact greetings works.
3751 public function testContactGreetingsCreateWithCustomField() {
3752 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
3753 $contact = $this->callAPISuccess('Contact', 'create', array('first_name' => 'Alan', 'contact_type' => 'Individual', 'custom_' . $ids['custom_field_id'] => 'Mice'));
3755 // Change postal greeting to involve a custom field.
3756 $postalOption = $this->callAPISuccessGetSingle('OptionValue', array('option_group_id' => 'postal_greeting', 'filter' => 1, 'is_default' => 1));
3757 $this->callAPISuccess('OptionValue', 'create', array(
3758 'id' => $postalOption['id'],
3759 'name' => 'Dear {contact.first_name} {contact.custom_' . $ids['custom_field_id'] . '}',
3760 'label' => 'Dear {contact.first_name} {contact.custom_' . $ids['custom_field_id'] . '}',
3763 // Update contact & see if postal greeting now reflects the new string.
3764 $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'last_name' => 'MouseyMousey'));
3765 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3766 $this->assertEquals('Dear Alan Mice', $contact['postal_greeting_display']);
3768 // Set contact to have no postal greeting & check it is correct.
3769 $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'postal_greeting_id' => 'null'));
3770 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3771 $this->assertEquals('', $contact['postal_greeting_display']);
3774 $this->callAPISuccess('OptionValue', 'create', array('id' => $postalOption['id'], 'name' => 'Dear {contact.first_name}'));
3775 $this->customFieldDelete($ids['custom_field_id']);
3776 $this->customGroupDelete($ids['custom_group_id']);
3780 * Test getunique api call for Contact entity
3782 public function testContactGetUnique() {
3783 $result = $this->callAPIAndDocument($this->_entity
, 'getunique', array(), __FUNCTION__
, __FILE__
);
3784 $this->assertEquals(1, $result['count']);
3785 $this->assertEquals(array('external_identifier'), $result['values']['UI_external_identifier']);
3788 public function testSmartGroupsForRelatedContacts() {
3789 $rtype1 = $this->callAPISuccess('relationship_type', 'create', array(
3790 "name_a_b" => uniqid() . " Child of",
3791 "name_b_a" => uniqid() . " Parent of",
3793 $rtype2 = $this->callAPISuccess('relationship_type', 'create', array(
3794 "name_a_b" => uniqid() . " Household Member of",
3795 "name_b_a" => uniqid() . " Household Member is",
3797 $h1 = $this->householdCreate();
3798 $c1 = $this->individualCreate(array('last_name' => 'Adams'));
3799 $c2 = $this->individualCreate(array('last_name' => 'Adams'));
3800 $this->callAPISuccess('relationship', 'create', array(
3801 'contact_id_a' => $c1,
3802 'contact_id_b' => $c2,
3804 'relationship_type_id' => $rtype1['id'], // Child of
3806 $this->callAPISuccess('relationship', 'create', array(
3807 'contact_id_a' => $c1,
3808 'contact_id_b' => $h1,
3810 'relationship_type_id' => $rtype2['id'], // Household Member of
3812 $this->callAPISuccess('relationship', 'create', array(
3813 'contact_id_a' => $c2,
3814 'contact_id_b' => $h1,
3816 'relationship_type_id' => $rtype2['id'], // Household Member of
3820 'formValues' => array(
3821 'display_relationship_type' => $rtype1['id'] . '_a_b', // Child of
3822 'sort_name' => 'Adams',
3825 $g1ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid()));
3827 'formValues' => array(
3828 'display_relationship_type' => $rtype2['id'] . '_a_b', // Household Member of
3831 $g2ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid()));
3833 'formValues' => array(
3834 'display_relationship_type' => $rtype2['id'] . '_b_a', // Household Member is
3837 // the reverse of g2 which adds another layer for overlap at related contact filter
3838 $g3ID = $this->smartGroupCreate($ssParams, array('name' => uniqid(), 'title' => uniqid()));
3839 CRM_Contact_BAO_GroupContactCache
::loadAll();
3840 $g1Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g1ID));
3841 $g2Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g2ID));
3842 $g3Contacts = $this->callAPISuccess('contact', 'get', array('group' => $g3ID));
3843 $this->assertTrue($g1Contacts['count'] == 1);
3844 $this->assertTrue($g2Contacts['count'] == 2);
3845 $this->assertTrue($g3Contacts['count'] == 1);