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 * Include class definitions
35 require_once 'CiviTest/CiviUnitTestCase.php';
39 * Test APIv3 civicrm_contact* functions
41 * @package CiviCRM_APIv3
42 * @subpackage API_Contact
44 class api_v3_ContactTest
extends CiviUnitTestCase
{
45 public $DBResetRequired = FALSE;
46 protected $_apiversion;
50 protected $_contactID;
51 protected $_financialTypeId = 1;
54 * Test setup for every test.
56 * Connect to the database, truncate the tables that will be used
57 * and redirect stdin to a temporary file
59 public function setUp() {
60 // Connect to the database.
62 $this->_apiversion
= 3;
63 $this->_entity
= 'contact';
64 $this->_params
= array(
65 'first_name' => 'abc1',
66 'contact_type' => 'Individual',
67 'last_name' => 'xyz1',
71 public function tearDown() {
72 // truncate a few tables
73 $tablesToTruncate = array(
76 'civicrm_contribution',
79 'civicrm_relationship',
84 $this->quickCleanup($tablesToTruncate, TRUE);
88 * Test civicrm_contact_create.
90 * Verify that attempt to create individual contact with only
91 * first and last names succeeds
93 public function testAddCreateIndividual() {
94 $oldCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
96 'first_name' => 'abc1',
97 'contact_type' => 'Individual',
98 'last_name' => 'xyz1',
101 $contact = $this->callAPISuccess('contact', 'create', $params);
102 $this->assertTrue(is_numeric($contact['id']));
103 $this->assertTrue($contact['id'] > 0);
104 $newCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
105 $this->assertEquals($oldCount +
1, $newCount);
107 $this->assertDBState('CRM_Contact_DAO_Contact',
114 * Test civicrm_contact_create with sub-types.
116 * Verify that sub-types are created successfully and not deleted by subsequent updates.
118 public function testIndividualSubType() {
120 'first_name' => 'test abc',
121 'contact_type' => 'Individual',
122 'last_name' => 'test xyz',
123 'contact_sub_type' => array('Student', 'Staff'),
125 $contact = $this->callAPISuccess('contact', 'create', $params);
126 $cid = $contact['id'];
130 'middle_name' => 'foo',
132 $this->callAPISuccess('contact', 'create', $params);
133 unset($params['middle_name']);
135 $contact = $this->callAPISuccess('contact', 'get', $params);
137 $this->assertEquals(array('Student', 'Staff'), $contact['values'][$cid]['contact_sub_type']);
141 * Verify that attempt to create contact with empty params fails.
143 public function testCreateEmptyContact() {
144 $this->callAPIFailure('contact', 'create', array());
148 * Verify that attempt to create contact with bad contact type fails.
150 public function testCreateBadTypeContact() {
152 'email' => 'man1@yahoo.com',
153 'contact_type' => 'Does not Exist',
155 $this->callAPIFailure('contact', 'create', $params, "'Does not Exist' is not a valid option for field contact_type");
159 * Verify that attempt to create individual contact without required fields fails.
161 public function testCreateBadRequiredFieldsIndividual() {
163 'middle_name' => 'This field is not required',
164 'contact_type' => 'Individual',
166 $this->callAPIFailure('contact', 'create', $params);
170 * Verify that attempt to create household contact without required fields fails.
172 public function testCreateBadRequiredFieldsHousehold() {
174 'middle_name' => 'This field is not required',
175 'contact_type' => 'Household',
177 $this->callAPIFailure('contact', 'create', $params);
181 * Test required field check.
183 * Verify that attempt to create organization contact without required fields fails.
185 public function testCreateBadRequiredFieldsOrganization() {
187 'middle_name' => 'This field is not required',
188 'contact_type' => 'Organization',
191 $this->callAPIFailure('contact', 'create', $params);
195 * Verify that attempt to create individual contact with only an email succeeds.
197 public function testCreateEmailIndividual() {
200 'email' => 'man3@yahoo.com',
201 'contact_type' => 'Individual',
202 'location_type_id' => 1,
205 $contact = $this->callAPISuccess('contact', 'create', $params);
207 $this->assertEquals(1, $contact['id']);
208 $email = $this->callAPISuccess('email', 'get', array('contact_id' => $contact['id']));
209 $this->assertEquals(1, $email['count']);
210 $this->assertEquals('man3@yahoo.com', $email['values'][$email['id']]['email']);
212 $this->callAPISuccess('contact', 'delete', $contact);
216 * Test creating individual by name.
218 * Verify create individual contact with only first and last names succeeds.
220 public function testCreateNameIndividual() {
222 'first_name' => 'abc1',
223 'contact_type' => 'Individual',
224 'last_name' => 'xyz1',
227 $contact = $this->callAPISuccess('contact', 'create', $params);
228 $this->assertEquals(1, $contact['id']);
232 * Test old keys still work.
234 * Verify that attempt to create individual contact with
235 * first and last names and old key values works
237 public function testCreateNameIndividualOldKeys() {
239 'individual_prefix' => 'Dr.',
240 'first_name' => 'abc1',
241 'contact_type' => 'Individual',
242 'last_name' => 'xyz1',
243 'individual_suffix' => 'Jr.',
246 $contact = $this->callAPISuccess('contact', 'create', $params);
247 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
249 $this->assertArrayKeyExists('prefix_id', $result);
250 $this->assertArrayKeyExists('suffix_id', $result);
251 $this->assertArrayKeyExists('gender_id', $result);
252 $this->assertEquals(4, $result['prefix_id']);
253 $this->assertEquals(1, $result['suffix_id']);
257 * Test preferred keys work.
259 * Verify that attempt to create individual contact with
260 * first and last names and old key values works
262 public function testCreateNameIndividualRecommendedKeys2() {
264 'prefix_id' => 'Dr.',
265 'first_name' => 'abc1',
266 'contact_type' => 'Individual',
267 'last_name' => 'xyz1',
268 'suffix_id' => 'Jr.',
269 'gender_id' => 'Male',
272 $contact = $this->callAPISuccess('contact', 'create', $params);
273 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
275 $this->assertArrayKeyExists('prefix_id', $result);
276 $this->assertArrayKeyExists('suffix_id', $result);
277 $this->assertArrayKeyExists('gender_id', $result);
278 $this->assertEquals(4, $result['prefix_id']);
279 $this->assertEquals(1, $result['suffix_id']);
283 * Test household name is sufficient for create.
285 * Verify that attempt to create household contact with only
286 * household name succeeds
288 public function testCreateNameHousehold() {
290 'household_name' => 'The abc Household',
291 'contact_type' => 'Household',
293 $contact = $this->callAPISuccess('contact', 'create', $params);
294 $this->assertEquals(1, $contact['id']);
298 * Test organization name is sufficient for create.
300 * Verify that attempt to create organization contact with only
301 * organization name succeeds.
303 public function testCreateNameOrganization() {
305 'organization_name' => 'The abc Organization',
306 'contact_type' => 'Organization',
308 $contact = $this->callAPISuccess('contact', 'create', $params);
309 $this->assertEquals(1, $contact['id']);
313 * Verify that attempt to create organization contact without organization name fails.
315 public function testCreateNoNameOrganization() {
317 'first_name' => 'The abc Organization',
318 'contact_type' => 'Organization',
320 $this->callAPIFailure('contact', 'create', $params);
324 * Check with complete array + custom field.
326 * Note that the test is written on purpose without any
327 * variables specific to participant so it can be replicated into other entities
328 * and / or moved to the automated test suite
330 public function testCreateWithCustom() {
331 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
333 $params = $this->_params
;
334 $params['custom_' . $ids['custom_field_id']] = "custom string";
335 $description = "This demonstrates setting a custom field through the API.";
336 $result = $this->callAPIAndDocument($this->_entity
, 'create', $params, __FUNCTION__
, __FILE__
, $description);
338 $check = $this->callAPISuccess($this->_entity
, 'get', array(
339 'return.custom_' . $ids['custom_field_id'] => 1,
340 'id' => $result['id'],
342 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
344 $this->customFieldDelete($ids['custom_field_id']);
345 $this->customGroupDelete($ids['custom_group_id']);
349 * CRM-12773 - expectation is that civicrm quietly ignores fields without values.
351 public function testCreateWithNULLCustomCRM12773() {
352 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
353 $params = $this->_params
;
354 $params['custom_' . $ids['custom_field_id']] = NULL;
355 $this->callAPISuccess('contact', 'create', $params);
356 $this->customFieldDelete($ids['custom_field_id']);
357 $this->customGroupDelete($ids['custom_group_id']);
362 * Test creating a current employer through API.
364 public function testContactCreateCurrentEmployer() {
365 // Here we will just do the get for set-up purposes.
366 $count = $this->callAPISuccess('contact', 'getcount', array(
367 'organization_name' => 'new employer org',
368 'contact_type' => 'Organization',
370 $this->assertEquals(0, $count);
371 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
372 'current_employer' => 'new employer org',
375 // do it again as an update to check it doesn't cause an error
376 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
377 'current_employer' => 'new employer org',
378 'id' => $employerResult['id'],
382 $this->callAPISuccess('contact', 'getcount', array(
383 'organization_name' => 'new employer org',
384 'contact_type' => 'Organization',
388 $result = $this->callAPISuccess('contact', 'getsingle', array(
389 'id' => $employerResult['id'],
392 $this->assertEquals('new employer org', $result['current_employer']);
397 * Test creating a current employer through API.
399 * Check it will re-activate a de-activated employer
401 public function testContactCreateDuplicateCurrentEmployerEnables() {
402 // Set up - create employer relationship.
403 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
404 'current_employer' => 'new employer org',
407 $relationship = $this->callAPISuccess('relationship', 'get', array(
408 'contact_id_a' => $employerResult['id'],
411 //disable & check it is disabled
412 $this->callAPISuccess('relationship', 'create', array('id' => $relationship['id'], 'is_active' => 0));
413 $this->callAPISuccess('relationship', 'getvalue', array(
414 'id' => $relationship['id'],
415 'return' => 'is_active',
418 // Re-set the current employer - thus enabling the relationship.
419 $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
420 'current_employer' => 'new employer org',
421 'id' => $employerResult['id'],
424 //check is_active is now 1
425 $relationship = $this->callAPISuccess('relationship', 'getsingle', array(
426 'return' => 'is_active',
428 $this->assertEquals(1, $relationship['is_active']);
432 * Check deceased contacts are not retrieved.
434 * Note at time of writing the default is to return default. This should possibly be changed & test added.
436 public function testGetDeceasedRetrieved() {
437 $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
438 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
439 'first_name' => 'bb',
440 'last_name' => 'ccc',
441 'contact_type' => 'Individual',
444 $result = $this->callAPISuccess($this->_entity
, 'get', array('is_deceased' => 0));
445 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
449 * Test that sort works - old syntax.
451 public function testGetSort() {
452 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
453 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
454 'first_name' => 'bb',
455 'last_name' => 'ccc',
456 'contact_type' => 'Individual',
458 $result = $this->callAPISuccess($this->_entity
, 'get', array(
459 'sort' => 'first_name ASC',
460 'return.first_name' => 1,
465 $this->assertEquals('abc1', $result['values'][0]['first_name']);
466 $result = $this->callAPISuccess($this->_entity
, 'get', array(
467 'sort' => 'first_name DESC',
468 'return.first_name' => 1,
472 $this->assertEquals('bb', $result['values'][0]['first_name']);
474 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
475 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
479 * Test that we can retrieve contacts using array syntax.
481 * I.e 'id' => array('IN' => array('3,4')).
483 public function testGetINIDArray() {
484 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
485 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
486 'first_name' => 'bb',
487 'last_name' => 'ccc',
488 'contact_type' => 'Individual',
490 $c3 = $this->callAPISuccess($this->_entity
, 'create', array(
491 'first_name' => 'hh',
493 'contact_type' => 'Individual',
495 $result = $this->callAPISuccess($this->_entity
, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
496 $this->assertEquals(2, $result['count']);
497 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
498 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
499 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
500 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c3['id']));
504 * Test variants on deleted behaviour.
506 public function testGetDeleted() {
507 $params = $this->_params
;
508 $contact1 = $this->callAPISuccess('contact', 'create', $params);
509 $params['is_deleted'] = 1;
510 $params['last_name'] = 'bcd';
511 $contact2 = $this->callAPISuccess('contact', 'create', $params);
512 $countActive = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'active'));
513 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all'));
514 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash'));
515 $countDefault = $this->callAPISuccess('contact', 'getcount', array());
516 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
517 'contact_is_deleted' => 1,
519 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
520 'contact_is_deleted' => 0,
522 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
523 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
524 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected in line ' . __LINE__
);
525 $this->assertEquals(1, $countActive);
526 $this->assertEquals(1, $countTrash);
527 $this->assertEquals(2, $countAll);
528 $this->assertEquals(1, $countDeleted);
529 $this->assertEquals(1, $countDefault, 'Only active by default in line ' . __LINE__
);
533 * Test that sort works - new syntax.
535 public function testGetSortNewSyntax() {
536 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
537 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
538 'first_name' => 'bb',
539 'last_name' => 'ccc',
540 'contact_type' => 'Individual',
542 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
543 'return' => 'first_name',
546 'sort' => 'first_name',
549 $this->assertEquals('abc1', $result, 'in line' . __LINE__
);
551 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
552 'return' => 'first_name',
555 'sort' => 'first_name DESC',
558 $this->assertEquals('bb', $result);
560 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
561 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
565 * Test apostrophe works in get & create.
567 public function testGetApostropheCRM10857() {
568 $params = array_merge($this->_params
, array('last_name' => "O'Connor"));
569 $this->callAPISuccess($this->_entity
, 'create', $params);
570 $result = $this->callAPISuccess($this->_entity
, 'getsingle', array(
571 'last_name' => "O'Connor",
574 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__
);
578 * Check with complete array + custom field.
580 * Note that the test is written on purpose without any
581 * variables specific to participant so it can be replicated into other entities
582 * and / or moved to the automated test suite
584 public function testGetWithCustom() {
585 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
587 $params = $this->_params
;
588 $params['custom_' . $ids['custom_field_id']] = "custom string";
589 $description = "This demonstrates setting a custom field through the API.";
590 $subfile = "CustomFieldGet";
591 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
593 $check = $this->callAPIAndDocument($this->_entity
, 'get', array(
594 'return.custom_' . $ids['custom_field_id'] => 1,
595 'id' => $result['id'],
596 ), __FUNCTION__
, __FILE__
, $description, $subfile);
598 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
599 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
600 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
601 $this->customFieldDelete($ids['custom_field_id']);
602 $this->customGroupDelete($ids['custom_group_id']);
606 * Check with complete array + custom field.
608 * Note that the test is written on purpose without any
609 * variables specific to participant so it can be replicated into other entities
610 * and / or moved to the automated test suite
612 public function testGetWithCustomReturnSyntax() {
613 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
615 $params = $this->_params
;
616 $params['custom_' . $ids['custom_field_id']] = "custom string";
617 $description = "This demonstrates setting a custom field through the API.";
618 $subfile = "CustomFieldGetReturnSyntaxVariation";
619 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
620 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
621 $check = $this->callAPIAndDocument($this->_entity
, 'get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
623 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
624 $this->customFieldDelete($ids['custom_field_id']);
625 $this->customGroupDelete($ids['custom_group_id']);
629 * Check that address name is returned if required.
631 public function testGetReturnAddressName() {
632 $contactID = $this->individualCreate();
633 $this->callAPISuccess('address', 'create', array(
634 'contact_id' => $contactID,
635 'address_name' => 'My house',
636 'location_type_id' => 'Home',
637 'street_address' => '1 my road',
639 $result = $this->callAPISuccessGetSingle('contact', array(
640 'return' => 'address_name, street_address',
643 $this->assertEquals('1 my road', $result['street_address']);
644 $this->assertEquals('My house', $result['address_name']);
648 public function testGetGroupIDFromContact() {
649 $groupId = $this->groupCreate();
650 $description = "Get all from group and display contacts.";
651 $subFile = "GroupFilterUsingContactAPI";
653 'email' => 'man2@yahoo.com',
654 'contact_type' => 'Individual',
655 'location_type_id' => 1,
656 'api.group_contact.create' => array('group_id' => $groupId),
659 $this->callAPISuccess('contact', 'create', $params);
660 // testing as integer
662 'filter.group_id' => $groupId,
663 'contact_type' => 'Individual',
665 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
666 $this->assertEquals(1, $result['count']);
667 // group 26 doesn't exist, but we can still search contacts in it.
669 'filter.group_id' => 26,
670 'contact_type' => 'Individual',
672 $this->callAPISuccess('contact', 'get', $params);
675 'filter.group_id' => "$groupId, 26",
676 'contact_type' => 'Individual',
678 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
679 $this->assertEquals(1, $result['count']);
681 'filter.group_id' => "26,27",
682 'contact_type' => 'Individual',
684 $this->callAPISuccess('contact', 'get', $params);
688 'filter.group_id' => array($groupId, 26),
689 'contact_type' => 'Individual',
691 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
692 $this->assertEquals(1, $result['count']);
694 //test in conjunction with other criteria
696 'filter.group_id' => array($groupId, 26),
697 'contact_type' => 'Organization',
699 $this->callAPISuccess('contact', 'get', $params);
701 'filter.group_id' => array(26, 27),
702 'contact_type' => 'Individual',
704 $result = $this->callAPISuccess('contact', 'get', $params);
705 $this->assertEquals(0, $result['count']);
709 * Verify that attempt to create individual contact with two chained websites succeeds.
711 public function testCreateIndividualWithContributionDottedSyntax() {
712 $description = "This demonstrates the syntax to create 2 chained entities.";
713 $subFile = "ChainTwoWebsites";
715 'first_name' => 'abc3',
716 'last_name' => 'xyz3',
717 'contact_type' => 'Individual',
718 'email' => 'man3@yahoo.com',
719 'api.contribution.create' => array(
720 'receive_date' => '2010-01-01',
721 'total_amount' => 100.00,
722 'financial_type_id' => $this->_financialTypeId
,
723 'payment_instrument_id' => 1,
724 'non_deductible_amount' => 10.00,
725 'fee_amount' => 50.00,
726 'net_amount' => 90.00,
728 'invoice_id' => 67990,
730 'contribution_status_id' => 1,
732 'api.website.create' => array(
733 'url' => "http://civicrm.org",
735 'api.website.create.2' => array(
736 'url' => "http://chained.org",
740 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
742 $this->assertEquals(1, $result['id']);
743 // checking child function result not covered in callAPIAndDocument
744 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
745 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url']);
746 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url']);
748 // delete the contact
749 $this->callAPISuccess('contact', 'delete', $result);
753 * Verify that attempt to create individual contact with chained contribution and website succeeds.
755 public function testCreateIndividualWithContributionChainedArrays() {
757 'first_name' => 'abc3',
758 'last_name' => 'xyz3',
759 'contact_type' => 'Individual',
760 'email' => 'man3@yahoo.com',
761 'api.contribution.create' => array(
762 'receive_date' => '2010-01-01',
763 'total_amount' => 100.00,
764 'financial_type_id' => $this->_financialTypeId
,
765 'payment_instrument_id' => 1,
766 'non_deductible_amount' => 10.00,
767 'fee_amount' => 50.00,
768 'net_amount' => 90.00,
770 'invoice_id' => 67890,
772 'contribution_status_id' => 1,
774 'api.website.create' => array(
776 'url' => "http://civicrm.org",
779 'url' => "http://chained.org",
780 'website_type_id' => 2,
785 $description = "Demonstrates creating two websites as an array.";
786 $subfile = "ChainTwoWebsitesSyntax2";
787 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
789 $this->assertEquals(1, $result['id']);
790 // the callAndDocument doesn't check the chained call
791 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error']);
792 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url']);
793 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url']);
795 $this->callAPISuccess('contact', 'delete', $result);
799 * Verify that attempt to create individual contact with first, and last names and email succeeds.
801 public function testCreateIndividualWithNameEmail() {
803 'first_name' => 'abc3',
804 'last_name' => 'xyz3',
805 'contact_type' => 'Individual',
806 'email' => 'man3@yahoo.com',
809 $contact = $this->callAPISuccess('contact', 'create', $params);
810 $this->assertEquals(1, $contact['id']);
812 $this->callAPISuccess('contact', 'delete', $contact);
816 * Verify that attempt to create individual contact with no data fails.
818 public function testCreateIndividualWithOutNameEmail() {
820 'contact_type' => 'Individual',
822 $this->callAPIFailure('contact', 'create', $params);
826 * Test create individual contact with first &last names, email and location type succeeds.
828 public function testCreateIndividualWithNameEmailLocationType() {
830 'first_name' => 'abc4',
831 'last_name' => 'xyz4',
832 'email' => 'man4@yahoo.com',
833 'contact_type' => 'Individual',
834 'location_type_id' => 1,
836 $result = $this->callAPISuccess('contact', 'create', $params);
838 $this->assertEquals(1, $result['id']);
840 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
844 * Verify that when changing employers the old employer relationship becomes inactive.
846 public function testCreateIndividualWithEmployer() {
847 $employer = $this->organizationCreate();
848 $employer2 = $this->organizationCreate();
851 'email' => 'man4@yahoo.com',
852 'contact_type' => 'Individual',
853 'employer_id' => $employer,
856 $result = $this->callAPISuccess('contact', 'create', $params);
857 $relationships = $this->callAPISuccess('relationship', 'get', array(
858 'contact_id_a' => $result['id'],
862 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
864 // Add more random relationships to make the test more realistic
865 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
866 $relTypeId = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
867 $this->callAPISuccess('relationship', 'create', array(
868 'contact_id_a' => $result['id'],
869 'contact_id_b' => $this->organizationCreate(),
871 'relationship_type_id' => $relTypeId,
875 // Add second employer
876 $params['employer_id'] = $employer2;
877 $params['id'] = $result['id'];
878 $result = $this->callAPISuccess('contact', 'create', $params);
880 $relationships = $this->callAPISuccess('relationship', 'get', array(
881 'contact_id_a' => $result['id'],
886 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
890 * Verify that attempt to create household contact with details succeeds.
892 public function testCreateHouseholdDetails() {
894 'household_name' => 'abc8\'s House',
895 'nick_name' => 'x House',
896 'email' => 'man8@yahoo.com',
897 'contact_type' => 'Household',
900 $contact = $this->callAPISuccess('contact', 'create', $params);
902 $this->assertEquals(1, $contact['id']);
904 $this->callAPISuccess('contact', 'delete', $contact);
908 * Verify that attempt to create household contact with inadequate details fails.
910 public function testCreateHouseholdInadequateDetails() {
912 'nick_name' => 'x House',
913 'email' => 'man8@yahoo.com',
914 'contact_type' => 'Household',
916 $this->callAPIFailure('contact', 'create', $params);
920 * Verify successful update of individual contact.
922 public function testUpdateIndividualWithAll() {
923 // Insert a row in civicrm_contact creating individual contact.
924 $op = new PHPUnit_Extensions_Database_Operation_Insert();
925 $op->execute($this->_dbconn
,
926 $this->createXMLDataSet(
927 dirname(__FILE__
) . '/dataset/contact_ind.xml'
933 'first_name' => 'abcd',
934 'contact_type' => 'Individual',
935 'nick_name' => 'This is nickname first',
936 'do_not_email' => '1',
937 'do_not_phone' => '1',
938 'do_not_mail' => '1',
939 'do_not_trade' => '1',
940 'legal_identifier' => 'ABC23853ZZ2235',
941 'external_identifier' => '1928837465',
942 'image_URL' => 'http://some.url.com/image.jpg',
943 'home_url' => 'http://www.example.org',
947 $this->callAPISuccess('Contact', 'Update', $params);
948 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
949 unset($params['contact_id']);
950 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
951 //reducing this test partially back to api v2 level to get it through
952 unset($params['home_url']);
953 foreach ($params as $key => $value) {
954 $this->assertEquals($value, $getResult['values'][23][$key]);
956 // Check updated civicrm_contact against expected.
957 $expected = $this->createXMLDataSet(
958 dirname(__FILE__
) . '/dataset/contact_ind_upd.xml'
960 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
963 $actual->addTable('civicrm_contact');
964 $expected->matches($actual);
968 * Verify successful update of organization contact.
970 public function testUpdateOrganizationWithAll() {
971 // Insert a row in civicrm_contact creating organization contact
972 $op = new PHPUnit_Extensions_Database_Operation_Insert();
973 $op->execute($this->_dbconn
,
974 $this->createXMLDataSet(
975 dirname(__FILE__
) . '/dataset/contact_org.xml'
981 'organization_name' => 'WebAccess India Pvt Ltd',
982 'legal_name' => 'WebAccess',
983 'sic_code' => 'ABC12DEF',
984 'contact_type' => 'Organization',
987 $this->callAPISuccess('Contact', 'Update', $params);
989 // Check updated civicrm_contact against expected.
990 $expected = $this->createXMLDataSet(
991 dirname(__FILE__
) . '/dataset/contact_org_upd.xml'
993 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
996 $actual->addTable('civicrm_contact');
997 $expected->matches($actual);
1001 * Verify successful update of household contact.
1003 public function testUpdateHouseholdWithAll() {
1004 // Insert a row in civicrm_contact creating household contact
1005 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1006 $op->execute($this->_dbconn
,
1007 $this->createXMLDataSet(
1008 dirname(__FILE__
) . '/dataset/contact_hld.xml'
1014 'household_name' => 'ABC household',
1015 'nick_name' => 'ABC House',
1016 'contact_type' => 'Household',
1019 $result = $this->callAPISuccess('Contact', 'Update', $params);
1022 'contact_type' => 'Household',
1024 'sort_name' => 'ABC household',
1025 'display_name' => 'ABC household',
1026 'nick_name' => 'ABC House',
1028 $this->getAndCheck($expected, $result['id'], 'contact');
1032 * Test civicrm_update() without contact type.
1034 * Deliberately exclude contact_type as it should still cope using civicrm_api.
1038 public function testUpdateCreateWithID() {
1039 // Insert a row in civicrm_contact creating individual contact.
1040 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1041 $op->execute($this->_dbconn
,
1042 $this->createXMLDataSet(
1043 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1049 'first_name' => 'abcd',
1050 'last_name' => 'wxyz',
1052 $this->callAPISuccess('Contact', 'Update', $params);
1056 * Test civicrm_contact_delete() with no contact ID.
1058 public function testContactDeleteNoID() {
1062 $this->callAPIFailure('contact', 'delete', $params);
1066 * Test civicrm_contact_delete() with error.
1068 public function testContactDeleteError() {
1069 $params = array('contact_id' => 999);
1070 $this->callAPIFailure('contact', 'delete', $params);
1074 * Test civicrm_contact_delete().
1076 public function testContactDelete() {
1077 $contactID = $this->individualCreate();
1081 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__
, __FILE__
);
1085 * Test civicrm_contact_get() return only first name.
1087 public function testContactGetRetFirst() {
1088 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1090 'contact_id' => $contact['id'],
1091 'return_first_name' => TRUE,
1092 'sort' => 'first_name',
1094 $result = $this->callAPISuccess('contact', 'get', $params);
1095 $this->assertEquals(1, $result['count']);
1096 $this->assertEquals($contact['id'], $result['id']);
1097 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1101 * Test civicrm_contact_get() return only first name & last name.
1103 * Use comma separated string return with a space.
1105 public function testContactGetReturnFirstLast() {
1106 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1108 'contact_id' => $contact['id'],
1109 'return' => 'first_name, last_name',
1111 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1112 $this->assertEquals('abc1', $result['first_name']);
1113 $this->assertEquals('xyz1', $result['last_name']);
1114 //check that other defaults not returns
1115 $this->assertArrayNotHasKey('sort_name', $result);
1117 'contact_id' => $contact['id'],
1118 'return' => 'first_name,last_name',
1120 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1121 $this->assertEquals('abc1', $result['first_name']);
1122 $this->assertEquals('xyz1', $result['last_name']);
1123 //check that other defaults not returns
1124 $this->assertArrayNotHasKey('sort_name', $result);
1128 * Test civicrm_contact_get() return only first name & last name.
1130 * Use comma separated string return without a space
1132 public function testContactGetReturnFirstLastNoComma() {
1133 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1135 'contact_id' => $contact['id'],
1136 'return' => 'first_name,last_name',
1138 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1139 $this->assertEquals('abc1', $result['first_name']);
1140 $this->assertEquals('xyz1', $result['last_name']);
1141 //check that other defaults not returns
1142 $this->assertArrayNotHasKey('sort_name', $result);
1146 * Test civicrm_contact_get() with default return properties.
1148 public function testContactGetRetDefault() {
1149 $contactID = $this->individualCreate();
1151 'contact_id' => $contactID,
1152 'sort' => 'first_name',
1154 $result = $this->callAPISuccess('contact', 'get', $params);
1155 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1156 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1160 * Test civicrm_contact_getquick() with empty name param.
1162 public function testContactGetQuick() {
1163 // Insert a row in civicrm_contact creating individual contact.
1164 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1165 $op->execute($this->_dbconn
,
1166 $this->createXMLDataSet(
1167 dirname(__FILE__
) . '/dataset/contact_17.xml'
1170 $op->execute($this->_dbconn
,
1171 $this->createXMLDataSet(
1172 dirname(__FILE__
) . '/dataset/email_contact_17.xml'
1179 $result = $this->callAPISuccess('contact', 'getquick', $params);
1180 $this->assertEquals(17, $result['values'][0]['id']);
1184 * Test civicrm_contact_get) with empty params.
1186 public function testContactGetEmptyParams() {
1187 $this->callAPISuccess('contact', 'get', array());
1191 * Test civicrm_contact_get(,true) with no matches.
1193 public function testContactGetOldParamsNoMatches() {
1194 // Insert a row in civicrm_contact creating contact 17.
1195 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1196 $op->execute($this->_dbconn
,
1197 $this->createXMLDataSet(
1198 dirname(__FILE__
) . '/dataset/contact_17.xml'
1203 'first_name' => 'Fred',
1205 $result = $this->callAPISuccess('contact', 'get', $params);
1206 $this->assertEquals(0, $result['count']);
1210 * Test civicrm_contact_get(,true) with one match.
1212 public function testContactGetOldParamsOneMatch() {
1213 // Insert a row in civicrm_contact creating contact 17
1214 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1215 $op->execute($this->_dbconn
,
1216 $this->createXMLDataSet(dirname(__FILE__
) . '/dataset/contact_17.xml'
1221 'first_name' => 'Test',
1223 $result = $this->callAPISuccess('contact', 'get', $params);
1224 $this->assertEquals(17, $result['values'][17]['contact_id']);
1225 $this->assertEquals(17, $result['id']);
1229 * Test civicrm_contact_search_count().
1231 public function testContactGetEmail() {
1233 'email' => 'man2@yahoo.com',
1234 'contact_type' => 'Individual',
1235 'location_type_id' => 1,
1238 $contact = $this->callAPISuccess('contact', 'create', $params);
1240 $this->assertEquals(1, $contact['id']);
1243 'email' => 'man2@yahoo.com',
1245 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
);
1246 $this->assertEquals(1, $result['values'][1]['contact_id']);
1247 $this->assertEquals('man2@yahoo.com', $result['values'][1]['email']);
1249 // delete the contact
1250 $this->callAPISuccess('contact', 'delete', $contact);
1254 * Test birth date parameters.
1256 * These include value, array & birth_date_high, birth_date_low
1259 public function testContactGetBirthDate() {
1260 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 2 years')));
1261 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 5 years')));
1262 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month -20 years')));
1264 $result = $this->callAPISuccess('contact', 'get', array());
1265 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1266 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1267 $this->assertEquals(1, $result['count']);
1268 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1269 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1270 $this->assertEquals(1, $result['count']);
1271 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1272 $result = $this->callAPISuccess('contact', 'get', array(
1273 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
1274 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
1276 $this->assertEquals(1, $result['count']);
1277 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1278 $result = $this->callAPISuccess('contact', 'get', array(
1279 'birth_date_low' => '-6 years',
1280 'birth_date_high' => '- 3 years',
1282 $this->assertEquals(1, $result['count']);
1283 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1287 * Test Deceased date parameters.
1289 * These include value, array & Deceased_date_high, Deceased date_low
1292 public function testContactGetDeceasedDate() {
1293 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 2 years')));
1294 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 5 years')));
1295 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month -20 years')));
1297 $result = $this->callAPISuccess('contact', 'get', array());
1298 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
1299 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
1300 $this->assertEquals(1, $result['count']);
1301 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1302 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
1303 $this->assertEquals(1, $result['count']);
1304 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
1305 $result = $this->callAPISuccess('contact', 'get', array(
1306 'deceased_date_low' => '-6 years',
1307 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
1309 $this->assertEquals(1, $result['count']);
1310 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1314 * Test for Contact.get id=@user:username.
1316 public function testContactGetByUsername() {
1317 // Setup - create contact with a uf-match.
1318 $cid = $this->individualCreate(array(
1319 'contact_type' => 'Individual',
1320 'first_name' => 'testGetByUsername',
1321 'last_name' => 'testGetByUsername',
1324 $ufMatchParams = array(
1325 'domain_id' => CRM_Core_Config
::domainID(),
1327 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
1328 'contact_id' => $cid,
1330 $ufMatch = CRM_Core_BAO_UFMatch
::create($ufMatchParams);
1331 $this->assertTrue(is_numeric($ufMatch->id
));
1333 // setup - mock the calls to CRM_Utils_System_*::getUfId
1334 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1335 $userSystem->expects($this->once())
1337 ->with($this->equalTo('exampleUser'))
1338 ->will($this->returnValue(99));
1339 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1342 $result = $this->callAPISuccess('Contact', 'get', array(
1343 'id' => '@user:exampleUser',
1345 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
1349 * Test to check return works OK.
1351 public function testContactGetReturnValues() {
1352 $extraParams = array('nick_name' => 'Bob', 'phone' => '456', 'email' => 'e@mail.com');
1353 $contactID = $this->individualCreate($extraParams);
1354 //actually it turns out the above doesn't create a phone
1355 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
1356 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
1357 foreach ($extraParams as $key => $value) {
1358 $this->assertEquals($result[$key], $value);
1360 //now we check they are still returned with 'return' key
1361 $result = $this->callAPISuccess('contact', 'getsingle', array(
1363 'return' => array_keys($extraParams),
1365 foreach ($extraParams as $key => $value) {
1366 $this->assertEquals($result[$key], $value);
1370 public function testCRM13252MultipleChainedPhones() {
1371 $contactID = $this->householdCreate();
1372 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
1374 'contact_id' => $contactID,
1375 'household_name' => 'Household 1',
1376 'contact_type' => 'Household',
1377 'api.phone.create' => array(
1379 'phone' => '111-111-1111',
1380 'location_type_id' => 1,
1381 'phone_type_id' => 1,
1384 'phone' => '222-222-2222',
1385 'location_type_id' => 1,
1386 'phone_type_id' => 2,
1390 $this->callAPISuccess('contact', 'create', $params);
1391 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
1396 * Test for Contact.get id=@user:username (with an invalid username).
1398 public function testContactGetByUnknownUsername() {
1399 // setup - mock the calls to CRM_Utils_System_*::getUfId
1400 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1401 $userSystem->expects($this->once())
1403 ->with($this->equalTo('exampleUser'))
1404 ->will($this->returnValue(NULL));
1405 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1408 $result = $this->callAPIFailure('Contact', 'get', array(
1409 'id' => '@user:exampleUser',
1411 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
1415 * Verify attempt to create individual with chained arrays.
1417 public function testGetIndividualWithChainedArrays() {
1418 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1419 $params['custom_' . $ids['custom_field_id']] = "custom string";
1421 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1422 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
1423 $subfile = "APIChainedArray";
1425 'first_name' => 'abc3',
1426 'last_name' => 'xyz3',
1427 'contact_type' => 'Individual',
1428 'email' => 'man3@yahoo.com',
1429 'api.contribution.create' => array(
1430 'receive_date' => '2010-01-01',
1431 'total_amount' => 100.00,
1432 'financial_type_id' => 1,
1433 'payment_instrument_id' => 1,
1434 'non_deductible_amount' => 10.00,
1435 'fee_amount' => 50.00,
1436 'net_amount' => 90.00,
1438 'invoice_id' => 67890,
1440 'contribution_status_id' => 1,
1442 'api.contribution.create.1' => array(
1443 'receive_date' => '2011-01-01',
1444 'total_amount' => 120.00,
1445 'financial_type_id' => $this->_financialTypeId
= 1,
1446 'payment_instrument_id' => 1,
1447 'non_deductible_amount' => 10.00,
1448 'fee_amount' => 50.00,
1449 'net_amount' => 90.00,
1451 'invoice_id' => 67830,
1453 'contribution_status_id' => 1,
1455 'api.website.create' => array(
1457 'url' => "http://civicrm.org",
1462 $result = $this->callAPISuccess('Contact', 'create', $params);
1464 'id' => $result['id'],
1465 'api.website.get' => array(),
1466 'api.Contribution.get' => array(
1467 'total_amount' => '120.00',
1469 'api.CustomValue.get' => 1,
1470 'api.Note.get' => 1,
1472 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1473 // delete the contact
1474 $this->callAPISuccess('contact', 'delete', $result);
1475 $this->customGroupDelete($ids['custom_group_id']);
1476 $this->customGroupDelete($moreIDs['custom_group_id']);
1477 $this->assertEquals(1, $result['id']);
1478 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
1479 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
1482 public function testGetIndividualWithChainedArraysFormats() {
1483 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
1484 $subfile = "APIChainedArrayFormats";
1485 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1486 $params['custom_' . $ids['custom_field_id']] = "custom string";
1488 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1490 'first_name' => 'abc3',
1491 'last_name' => 'xyz3',
1492 'contact_type' => 'Individual',
1493 'email' => 'man3@yahoo.com',
1494 'api.contribution.create' => array(
1495 'receive_date' => '2010-01-01',
1496 'total_amount' => 100.00,
1497 'financial_type_id' => $this->_financialTypeId
,
1498 'payment_instrument_id' => 1,
1499 'non_deductible_amount' => 10.00,
1500 'fee_amount' => 50.00,
1501 'net_amount' => 90.00,
1503 'contribution_status_id' => 1,
1505 'api.contribution.create.1' => array(
1506 'receive_date' => '2011-01-01',
1507 'total_amount' => 120.00,
1508 'financial_type_id' => $this->_financialTypeId
,
1509 'payment_instrument_id' => 1,
1510 'non_deductible_amount' => 10.00,
1511 'fee_amount' => 50.00,
1512 'net_amount' => 90.00,
1514 'contribution_status_id' => 1,
1516 'api.website.create' => array(
1518 'url' => "http://civicrm.org",
1523 $result = $this->callAPISuccess('Contact', 'create', $params);
1525 'id' => $result['id'],
1526 'api.website.getValue' => array('return' => 'url'),
1527 'api.Contribution.getCount' => array(),
1528 'api.CustomValue.get' => 1,
1529 'api.Note.get' => 1,
1530 'api.Membership.getCount' => array(),
1532 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1533 $this->assertEquals(1, $result['id']);
1534 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
1535 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
1536 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
1538 $this->callAPISuccess('contact', 'delete', $result);
1539 $this->customGroupDelete($ids['custom_group_id']);
1540 $this->customGroupDelete($moreIDs['custom_group_id']);
1544 * Test complex chaining.
1546 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
1547 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1548 $params['custom_' . $ids['custom_field_id']] = "custom string";
1549 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1550 $andMoreIDs = $this->CustomGroupMultipleCreateWithFields(array(
1551 'title' => "another group",
1552 'name' => 'another name',
1554 $description = "This demonstrates the usage of chained api functions with multiple custom fields.";
1555 $subfile = "APIChainedArrayMultipleCustom";
1557 'first_name' => 'abc3',
1558 'last_name' => 'xyz3',
1559 'contact_type' => 'Individual',
1560 'email' => 'man3@yahoo.com',
1561 'api.contribution.create' => array(
1562 'receive_date' => '2010-01-01',
1563 'total_amount' => 100.00,
1564 'financial_type_id' => 1,
1565 'payment_instrument_id' => 1,
1566 'non_deductible_amount' => 10.00,
1567 'fee_amount' => 50.00,
1568 'net_amount' => 90.00,
1570 'invoice_id' => 67890,
1572 'contribution_status_id' => 1,
1574 'api.contribution.create.1' => array(
1575 'receive_date' => '2011-01-01',
1576 'total_amount' => 120.00,
1577 'financial_type_id' => 1,
1578 'payment_instrument_id' => 1,
1579 'non_deductible_amount' => 10.00,
1580 'fee_amount' => 50.00,
1581 'net_amount' => 90.00,
1583 'invoice_id' => 67830,
1585 'contribution_status_id' => 1,
1587 'api.website.create' => array(
1589 'url' => "http://civicrm.org",
1592 'custom_' . $ids['custom_field_id'] => "value 1",
1593 'custom_' . $moreIDs['custom_field_id'][0] => "value 2",
1594 'custom_' . $moreIDs['custom_field_id'][1] => "warm beer",
1595 'custom_' . $andMoreIDs['custom_field_id'][1] => "vegemite",
1598 $result = $this->callAPISuccess('Contact', 'create', $params);
1599 $result = $this->callAPISuccess('Contact', 'create', array(
1600 'contact_type' => 'Individual',
1601 'id' => $result['id'],
1603 $moreIDs['custom_field_id'][0] => "value 3",
1605 $ids['custom_field_id'] => "value 4",
1609 'id' => $result['id'],
1610 'api.website.getValue' => array('return' => 'url'),
1611 'api.Contribution.getCount' => array(),
1612 'api.CustomValue.get' => 1,
1614 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1616 $this->customGroupDelete($ids['custom_group_id']);
1617 $this->customGroupDelete($moreIDs['custom_group_id']);
1618 $this->customGroupDelete($andMoreIDs['custom_group_id']);
1619 $this->assertEquals(1, $result['id']);
1620 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
1621 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
1625 * Test checks usage of $values to pick & choose inputs.
1627 public function testChainingValuesCreate() {
1628 $description = "This demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
1629 2 child functions - one receives values from the parent (Contact) and the other child (Tag).";
1630 $subfile = "APIChainedArrayValuesFromSiblingFunction";
1632 'display_name' => 'batman',
1633 'contact_type' => 'Individual',
1634 'api.tag.create' => array('name' => '$value.id', 'description' => '$value.display_name', 'format.only_id' => 1),
1635 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
1637 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1638 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
1640 $tablesToTruncate = array(
1643 'civicrm_entity_tag',
1646 $this->quickCleanup($tablesToTruncate, TRUE);
1650 * Test TrueFalse format - I couldn't come up with an easy way to get an error on Get.
1652 public function testContactGetFormatIsSuccessTrue() {
1653 $this->createContactFromXML();
1654 $description = "This demonstrates use of the 'format.is_success' param.
1655 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1656 $subfile = "FormatIsSuccess_True";
1657 $params = array('id' => 17, 'format.is_success' => 1);
1658 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1659 $this->assertEquals(1, $result);
1660 $this->callAPISuccess('Contact', 'Delete', $params);
1664 * Test TrueFalse format.
1666 public function testContactCreateFormatIsSuccessFalse() {
1668 $description = "This demonstrates use of the 'format.is_success' param.
1669 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1670 $subfile = "FormatIsSuccess_Fail";
1671 $params = array('id' => 500, 'format.is_success' => 1);
1672 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1673 $this->assertEquals(0, $result);
1677 * Test Single Entity format.
1679 public function testContactGetSingleEntityArray() {
1680 $this->createContactFromXML();
1681 $description = "This demonstrates use of the 'format.single_entity_array' param.
1682 This param causes the only contact to be returned as an array without the other levels.
1683 It will be ignored if there is not exactly 1 result";
1684 $subfile = "GetSingleContact";
1685 $params = array('id' => 17);
1686 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1687 $this->assertEquals('Test Contact', $result['display_name']);
1688 $this->callAPISuccess('Contact', 'Delete', $params);
1692 * Test Single Entity format.
1694 public function testContactGetFormatCountOnly() {
1695 $this->createContactFromXML();
1696 $description = "This demonstrates use of the 'getCount' action.
1697 This param causes the count of the only function to be returned as an integer.";
1698 $subfile = "GetCountContact";
1699 $params = array('id' => 17);
1700 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__
, __FILE__
, $description,
1701 $subfile, 'getcount');
1702 $this->assertEquals('1', $result);
1703 $this->callAPISuccess('Contact', 'Delete', $params);
1707 * Test id only format.
1709 public function testContactGetFormatIDOnly() {
1710 $this->createContactFromXML();
1711 $description = "This demonstrates use of the 'format.id_only' param.
1712 This param causes the id of the only entity to be returned as an integer.
1713 It will be ignored if there is not exactly 1 result";
1714 $subfile = "FormatOnlyID";
1715 $params = array('id' => 17, 'format.only_id' => 1);
1716 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1717 $this->assertEquals('17', $result);
1718 $this->callAPISuccess('Contact', 'Delete', $params);
1722 * Test id only format.
1724 public function testContactGetFormatSingleValue() {
1725 $this->createContactFromXML();
1726 $description = "This demonstrates use of the 'format.single_value' param.
1727 This param causes only a single value of the only entity to be returned as an string.
1728 It will be ignored if there is not exactly 1 result";
1729 $subFile = "FormatSingleValue";
1730 $params = array('id' => 17, 'return' => 'display_name');
1731 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__
, __FILE__
, $description, $subFile, 'getvalue');
1732 $this->assertEquals('Test Contact', $result);
1733 $this->callAPISuccess('Contact', 'Delete', $params);
1737 * Test that permissions are respected when creating contacts.
1739 public function testContactCreationPermissions() {
1741 'contact_type' => 'Individual',
1742 'first_name' => 'Foo',
1743 'last_name' => 'Bear',
1744 'check_permissions' => TRUE,
1746 $config = CRM_Core_Config
::singleton();
1747 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1748 $result = $this->callAPIFailure('contact', 'create', $params);
1749 $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');
1751 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'add contacts', 'import contacts');
1752 $this->callAPISuccess('contact', 'create', $params, NULL, 'overfluous permissions should be enough to create a contact');
1756 * Test update with check permissions set.
1758 public function testContactUpdatePermissions() {
1760 'contact_type' => 'Individual',
1761 'first_name' => 'Foo',
1762 'last_name' => 'Bear',
1763 'check_permissions' => TRUE,
1765 $result = $this->callAPISuccess('contact', 'create', $params);
1766 $config = CRM_Core_Config
::singleton();
1768 'id' => $result['id'],
1769 'contact_type' => 'Individual',
1770 'last_name' => 'Bar',
1771 'check_permissions' => TRUE,
1774 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1775 $result = $this->callAPIFailure('contact', 'update', $params);
1776 $this->assertEquals('API permission check failed for contact/update call; insufficient permission: require access CiviCRM and edit all contacts', $result['error_message'], 'lacking permissions should not be enough to update a contact');
1778 $config->userPermissionClass
->permissions
= array(
1781 'view all contacts',
1782 'edit all contacts',
1785 $this->callAPISuccess('contact', 'update', $params, NULL, 'overfluous permissions should be enough to update a contact');
1789 * Set up helper to create a contact.
1791 public function createContactFromXML() {
1792 // Insert a row in civicrm_contact creating contact 17.
1793 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1794 $op->execute($this->_dbconn
,
1795 $this->createXMLDataSet(
1796 dirname(__FILE__
) . '/dataset/contact_17.xml'
1802 * Test contact proximity api.
1804 public function testContactProximity() {
1805 // first create a contact with a SF location with a specific
1807 $contactID = $this->organizationCreate();
1809 // now create the address
1811 'street_address' => '123 Main Street',
1812 'city' => 'San Francisco',
1814 'country_id' => 1228,
1815 'state_province_id' => 1004,
1816 'geo_code_1' => '37.79',
1817 'geo_code_2' => '-122.40',
1818 'location_type_id' => 1,
1819 'contact_id' => $contactID,
1822 $result = $this->callAPISuccess('address', 'create', $params);
1823 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1825 // now do a proximity search with a close enough geocode and hope to match
1826 // that specific contact only!
1827 $proxParams = array(
1829 'longitude' => -122.3,
1833 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
1834 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1838 * Test that Ajax API permission is sufficient to access getquick api.
1840 * (note that getquick api is required for autocomplete & has ACL permissions applied)
1842 public function testGetquickPermissionCRM13744() {
1843 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviEvent');
1844 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1845 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
1846 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1847 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access AJAX API');
1848 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1852 * Test get ref api - gets a list of references to an entity.
1854 public function testGetReferenceCounts() {
1855 $result = $this->callAPISuccess('Contact', 'create', array(
1856 'first_name' => 'Testily',
1857 'last_name' => 'McHaste',
1858 'contact_type' => 'Individual',
1859 'api.Address.replace' => array(
1860 'values' => array(),
1862 'api.Email.replace' => array(
1865 'email' => 'spam@dev.null',
1867 'location_type_id' => 1,
1871 'api.Phone.replace' => array(
1874 'phone' => '234-567-0001',
1876 'location_type_id' => 1,
1879 'phone' => '234-567-0002',
1881 'location_type_id' => 1,
1887 //$dao = new CRM_Contact_BAO_Contact();
1888 //$dao->id = $result['id'];
1889 //$this->assertTrue((bool) $dao->find(TRUE));
1891 //$refCounts = $dao->getReferenceCounts();
1892 //$this->assertTrue(is_array($refCounts));
1893 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
1895 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
1896 'id' => $result['id'],
1898 $refCountsIdx = CRM_Utils_Array
::index(array('name'), $refCounts['values']);
1900 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
1901 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
1902 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
1903 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
1904 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
1907 public function testSQLOperatorsOnContactAPI() {
1908 $this->individualCreate();
1909 $this->organizationCreate();
1910 $this->householdCreate();
1911 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
1912 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
1913 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
1914 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
1918 * CRM-14743 - test api respects search operators.
1920 public function testGetModifiedDateByOperators() {
1921 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1922 $contact1 = $this->individualCreate();
1923 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
1924 CRM_Core_DAO
::executeQuery($sql);
1925 $contact2 = $this->individualCreate();
1926 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
1927 CRM_Core_DAO
::executeQuery($sql);
1928 $contact3 = $this->householdCreate();
1929 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
1930 CRM_Core_DAO
::executeQuery($sql);
1931 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
1932 $this->assertEquals($contacts['count'], 3);
1933 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
1934 $this->assertEquals($contacts['count'], $preExistingContactCount);
1938 * CRM-14743 - test api respects search operators.
1940 public function testGetCreatedDateByOperators() {
1941 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1942 $contact1 = $this->individualCreate();
1943 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
1944 CRM_Core_DAO
::executeQuery($sql);
1945 $contact2 = $this->individualCreate();
1946 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
1947 CRM_Core_DAO
::executeQuery($sql);
1948 $contact3 = $this->householdCreate();
1949 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
1950 CRM_Core_DAO
::executeQuery($sql);
1951 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
1952 $this->assertEquals($contacts['count'], 3);
1953 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
1954 $this->assertEquals($contacts['count'], $preExistingContactCount);
1958 * CRM-14263 check that API is not affected by search profile related bug.
1960 public function testReturnCityProfile() {
1961 $contactID = $this->individualCreate();
1962 CRM_Core_Config
::singleton()->defaultSearchProfileID
= 1;
1963 $this->callAPISuccess('address', 'create', array(
1964 'contact_id' => $contactID,
1965 'city' => 'Cool City',
1966 'location_type_id' => 1,
1968 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
1969 $this->assertEquals(1, $result['count']);
1973 * CRM-15443 - ensure getlist api does not return deleted contacts
1975 public function testGetlistExcludeConditions() {
1976 $name = md5(time());
1977 $contact = $this->individualCreate(array('last_name' => $name));
1978 $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
1979 $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
1980 // We should get all but the deleted contact.
1981 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
1982 $this->assertEquals(2, $result['count'], 'In line ' . __LINE__
);
1983 // Force-exclude the deceased contact.
1984 $result = $this->callAPISuccess('contact', 'getlist', array(
1986 'params' => array('is_deceased' => 0),
1988 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1989 $this->assertEquals($contact, $result['values'][0]['id'], 'In line ' . __LINE__
);
1993 * Test contact getactions.
1995 public function testGetActions() {
1996 $description = "Getting the available actions for an entity.";
1997 $result = $this->callAPIAndDocument($this->_entity
, 'getactions', array(), __FUNCTION__
, __FILE__
, $description);
2017 $deprecated = array(
2021 foreach ($expected as $action) {
2022 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
2024 foreach ($deprecated as $action) {
2025 $this->assertArrayKeyExists($action, $result['deprecated']);