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']), "In line " . __LINE__
);
103 $this->assertTrue($contact['id'] > 0, "In line " . __LINE__
);
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'], "In line " . __LINE__
);
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'], "In line " . __LINE__
);
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'], "In line " . __LINE__
);
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, 'in line ' . __LINE__
);
526 $this->assertEquals(1, $countTrash, 'in line ' . __LINE__
);
527 $this->assertEquals(2, $countAll, 'in line ' . __LINE__
);
528 $this->assertEquals(1, $countDeleted, 'in line ' . __LINE__
);
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 = "test 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'], "In line " . __LINE__
);
746 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url'], "In line " . __LINE__
);
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'], "In line " . __LINE__
);
792 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url'], "In line " . __LINE__
);
793 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url'], "In line " . __LINE__
);
795 $this->callAPISuccess('contact', 'delete', $result);
799 * Verify that attempt to create individual contact with first
800 * and last names and email succeeds
802 public function testCreateIndividualWithNameEmail() {
804 'first_name' => 'abc3',
805 'last_name' => 'xyz3',
806 'contact_type' => 'Individual',
807 'email' => 'man3@yahoo.com',
810 $contact = $this->callAPISuccess('contact', 'create', $params);
811 $this->assertEquals(1, $contact['id'], "In line " . __LINE__
);
813 // delete the contact
814 $this->callAPISuccess('contact', 'delete', $contact);
818 * Verify that attempt to create individual contact with no data fails
820 public function testCreateIndividualWithOutNameEmail() {
822 'contact_type' => 'Individual',
824 $this->callAPIFailure('contact', 'create', $params);
828 * Verify that attempt to create individual contact with first
829 * and last names, email and location type succeeds
831 public function testCreateIndividualWithNameEmailLocationType() {
833 'first_name' => 'abc4',
834 'last_name' => 'xyz4',
835 'email' => 'man4@yahoo.com',
836 'contact_type' => 'Individual',
837 'location_type_id' => 1,
839 $result = $this->callAPISuccess('contact', 'create', $params);
841 $this->assertEquals(1, $result['id'], "In line " . __LINE__
);
843 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
847 * Verify that when changing employers
848 * the old employer relationship becomes inactive
850 public function testCreateIndividualWithEmployer() {
851 $employer = $this->organizationCreate();
852 $employer2 = $this->organizationCreate();
855 'email' => 'man4@yahoo.com',
856 'contact_type' => 'Individual',
857 'employer_id' => $employer,
860 $result = $this->callAPISuccess('contact', 'create', $params);
861 $relationships = $this->callAPISuccess('relationship', 'get', array(
862 'contact_id_a' => $result['id'],
866 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
868 // Add more random relationships to make the test more realistic
869 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
870 $relTypeId = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
871 $this->callAPISuccess('relationship', 'create', array(
872 'contact_id_a' => $result['id'],
873 'contact_id_b' => $this->organizationCreate(),
875 'relationship_type_id' => $relTypeId,
879 // Add second employer
880 $params['employer_id'] = $employer2;
881 $params['id'] = $result['id'];
882 $result = $this->callAPISuccess('contact', 'create', $params);
884 $relationships = $this->callAPISuccess('relationship', 'get', array(
885 'contact_id_a' => $result['id'],
890 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
894 * Verify that attempt to create household contact with details
897 public function testCreateHouseholdDetails() {
899 'household_name' => 'abc8\'s House',
900 'nick_name' => 'x House',
901 'email' => 'man8@yahoo.com',
902 'contact_type' => 'Household',
905 $contact = $this->callAPISuccess('contact', 'create', $params);
907 $this->assertEquals(1, $contact['id'], "In line " . __LINE__
);
909 $this->callAPISuccess('contact', 'delete', $contact);
913 * Verify that attempt to create household contact with inadequate details fails.
915 public function testCreateHouseholdInadequateDetails() {
917 'nick_name' => 'x House',
918 'email' => 'man8@yahoo.com',
919 'contact_type' => 'Household',
921 $this->callAPIFailure('contact', 'create', $params);
925 * Verify successful update of individual contact.
927 public function testUpdateIndividualWithAll() {
928 // Insert a row in civicrm_contact creating individual contact.
929 $op = new PHPUnit_Extensions_Database_Operation_Insert();
930 $op->execute($this->_dbconn
,
931 $this->createXMLDataSet(
932 dirname(__FILE__
) . '/dataset/contact_ind.xml'
938 'first_name' => 'abcd',
939 'contact_type' => 'Individual',
940 'nick_name' => 'This is nickname first',
941 'do_not_email' => '1',
942 'do_not_phone' => '1',
943 'do_not_mail' => '1',
944 'do_not_trade' => '1',
945 'legal_identifier' => 'ABC23853ZZ2235',
946 'external_identifier' => '1928837465',
947 'image_URL' => 'http://some.url.com/image.jpg',
948 'home_url' => 'http://www.example.org',
952 $this->callAPISuccess('Contact', 'Update', $params);
953 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
954 unset($params['contact_id']);
955 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
956 //reducing this test partially back to api v2 level to get it through
957 unset($params['home_url']);
958 foreach ($params as $key => $value) {
959 $this->assertEquals($value, $getResult['values'][23][$key]);
961 // Check updated civicrm_contact against expected.
962 $expected = $this->createXMLDataSet(
963 dirname(__FILE__
) . '/dataset/contact_ind_upd.xml'
965 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
968 $actual->addTable('civicrm_contact');
969 $expected->matches($actual);
973 * Verify successful update of organization contact
975 public function testUpdateOrganizationWithAll() {
976 // Insert a row in civicrm_contact creating organization contact
977 $op = new PHPUnit_Extensions_Database_Operation_Insert();
978 $op->execute($this->_dbconn
,
979 $this->createXMLDataSet(
980 dirname(__FILE__
) . '/dataset/contact_org.xml'
986 'organization_name' => 'WebAccess India Pvt Ltd',
987 'legal_name' => 'WebAccess',
988 'sic_code' => 'ABC12DEF',
989 'contact_type' => 'Organization',
992 $this->callAPISuccess('Contact', 'Update', $params);
994 // Check updated civicrm_contact against expected.
995 $expected = $this->createXMLDataSet(
996 dirname(__FILE__
) . '/dataset/contact_org_upd.xml'
998 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1001 $actual->addTable('civicrm_contact');
1002 $expected->matches($actual);
1006 * Verify successful update of household contact.
1008 public function testUpdateHouseholdWithAll() {
1009 // Insert a row in civicrm_contact creating household contact
1010 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1011 $op->execute($this->_dbconn
,
1012 $this->createXMLDataSet(
1013 dirname(__FILE__
) . '/dataset/contact_hld.xml'
1019 'household_name' => 'ABC household',
1020 'nick_name' => 'ABC House',
1021 'contact_type' => 'Household',
1024 $result = $this->callAPISuccess('Contact', 'Update', $params);
1027 'contact_type' => 'Household',
1029 'sort_name' => 'ABC household',
1030 'display_name' => 'ABC household',
1031 'nick_name' => 'ABC House',
1033 $this->getAndCheck($expected, $result['id'], 'contact');
1037 * Test civicrm_update() without contact type.
1039 * Deliberately exclude contact_type as it should still cope using civicrm_api.
1043 public function testUpdateCreateWithID() {
1044 // Insert a row in civicrm_contact creating individual contact.
1045 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1046 $op->execute($this->_dbconn
,
1047 $this->createXMLDataSet(
1048 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1054 'first_name' => 'abcd',
1055 'last_name' => 'wxyz',
1057 $this->callAPISuccess('Contact', 'Update', $params);
1061 * Test civicrm_contact_delete() with no contact ID.
1063 public function testContactDeleteNoID() {
1067 $this->callAPIFailure('contact', 'delete', $params);
1071 * Test civicrm_contact_delete() with error.
1073 public function testContactDeleteError() {
1074 $params = array('contact_id' => 999);
1075 $this->callAPIFailure('contact', 'delete', $params);
1079 * Test civicrm_contact_delete().
1081 public function testContactDelete() {
1082 $contactID = $this->individualCreate();
1086 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__
, __FILE__
);
1090 * Test civicrm_contact_get() return only first name.
1092 public function testContactGetRetFirst() {
1093 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1095 'contact_id' => $contact['id'],
1096 'return_first_name' => TRUE,
1097 'sort' => 'first_name',
1099 $result = $this->callAPISuccess('contact', 'get', $params);
1100 $this->assertEquals(1, $result['count']);
1101 $this->assertEquals($contact['id'], $result['id']);
1102 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1106 * Test civicrm_contact_get() return only first name & last name.
1108 * Use comma separated string return with a space.
1110 public function testContactGetReturnFirstLast() {
1111 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1113 'contact_id' => $contact['id'],
1114 'return' => 'first_name, last_name',
1116 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1117 $this->assertEquals('abc1', $result['first_name']);
1118 $this->assertEquals('xyz1', $result['last_name']);
1119 //check that other defaults not returns
1120 $this->assertArrayNotHasKey('sort_name', $result);
1122 'contact_id' => $contact['id'],
1123 'return' => 'first_name,last_name',
1125 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1126 $this->assertEquals('abc1', $result['first_name']);
1127 $this->assertEquals('xyz1', $result['last_name']);
1128 //check that other defaults not returns
1129 $this->assertArrayNotHasKey('sort_name', $result);
1133 * Test civicrm_contact_get() return only first name & last name.
1135 * Use comma separated string return without a space
1137 public function testContactGetReturnFirstLastNoComma() {
1138 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1140 'contact_id' => $contact['id'],
1141 'return' => 'first_name,last_name',
1143 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1144 $this->assertEquals('abc1', $result['first_name']);
1145 $this->assertEquals('xyz1', $result['last_name']);
1146 //check that other defaults not returns
1147 $this->assertArrayNotHasKey('sort_name', $result);
1151 * Test civicrm_contact_get() with default return properties.
1153 public function testContactGetRetDefault() {
1154 $contactID = $this->individualCreate();
1156 'contact_id' => $contactID,
1157 'sort' => 'first_name',
1159 $result = $this->callAPISuccess('contact', 'get', $params);
1160 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1161 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1165 * Test civicrm_contact_getquick() with empty name param.
1167 public function testContactGetQuick() {
1168 // Insert a row in civicrm_contact creating individual contact
1169 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1170 $op->execute($this->_dbconn
,
1171 $this->createXMLDataSet(
1172 dirname(__FILE__
) . '/dataset/contact_17.xml'
1175 $op->execute($this->_dbconn
,
1176 $this->createXMLDataSet(
1177 dirname(__FILE__
) . '/dataset/email_contact_17.xml'
1184 $result = $this->callAPISuccess('contact', 'getquick', $params);
1185 $this->assertEquals(17, $result['values'][0]['id'], 'in line ' . __LINE__
);
1189 * Test civicrm_contact_get) with empty params
1191 public function testContactGetEmptyParams() {
1192 $this->callAPISuccess('contact', 'get', array());
1196 * Test civicrm_contact_get(,true) with no matches
1198 public function testContactGetOldParamsNoMatches() {
1199 // Insert a row in civicrm_contact creating contact 17
1200 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1201 $op->execute($this->_dbconn
,
1202 $this->createXMLDataSet(
1203 dirname(__FILE__
) . '/dataset/contact_17.xml'
1208 'first_name' => 'Fred',
1210 $result = $this->callAPISuccess('contact', 'get', $params);
1211 $this->assertEquals(0, $result['count'], 'in line ' . __LINE__
);
1215 * Test civicrm_contact_get(,true) with one match
1217 public function testContactGetOldParamsOneMatch() {
1218 // Insert a row in civicrm_contact creating contact 17
1219 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1220 $op->execute($this->_dbconn
,
1221 $this->createXMLDataSet(dirname(__FILE__
) . '/dataset/contact_17.xml'
1226 'first_name' => 'Test',
1228 $result = $this->callAPISuccess('contact', 'get', $params);
1229 $this->assertEquals(17, $result['values'][17]['contact_id'], 'in line ' . __LINE__
);
1230 $this->assertEquals(17, $result['id'], 'in line ' . __LINE__
);
1234 * Test civicrm_contact_search_count()
1236 public function testContactGetEmail() {
1238 'email' => 'man2@yahoo.com',
1239 'contact_type' => 'Individual',
1240 'location_type_id' => 1,
1243 $contact = $this->callAPISuccess('contact', 'create', $params);
1245 $this->assertEquals(1, $contact['id']);
1248 'email' => 'man2@yahoo.com',
1250 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
);
1251 $this->assertEquals(1, $result['values'][1]['contact_id']);
1252 $this->assertEquals('man2@yahoo.com', $result['values'][1]['email']);
1254 // delete the contact
1255 $this->callAPISuccess('contact', 'delete', $contact);
1259 * Test birth date params incl value, array & birth_date_high, birth_date_low
1262 public function testContactGetBirthDate() {
1263 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 2 years')));
1264 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 5 years')));
1265 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month -20 years')));
1267 $result = $this->callAPISuccess('contact', 'get', array());
1268 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1269 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1270 $this->assertEquals(1, $result['count']);
1271 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1272 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1273 $this->assertEquals(1, $result['count']);
1274 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1275 $result = $this->callAPISuccess('contact', 'get', array(
1276 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
1277 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
1279 $this->assertEquals(1, $result['count']);
1280 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1281 $result = $this->callAPISuccess('contact', 'get', array(
1282 'birth_date_low' => '-6 years',
1283 'birth_date_high' => '- 3 years',
1285 $this->assertEquals(1, $result['count']);
1286 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1290 * Test Deceased date params incl value, array & Deceased_date_high, Deceased date_low
1293 public function testContactGetDeceasedDate() {
1294 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 2 years')));
1295 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 5 years')));
1296 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month -20 years')));
1298 $result = $this->callAPISuccess('contact', 'get', array());
1299 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
1300 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
1301 $this->assertEquals(1, $result['count']);
1302 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1303 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
1304 $this->assertEquals(1, $result['count']);
1305 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
1306 $result = $this->callAPISuccess('contact', 'get', array(
1307 'deceased_date_low' => '-6 years',
1308 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
1310 $this->assertEquals(1, $result['count']);
1311 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1315 * Test for Contact.get id=@user:username
1317 public function testContactGetByUsername() {
1318 // setup - create contact with a uf-match
1319 $cid = $this->individualCreate(array(
1320 'contact_type' => 'Individual',
1321 'first_name' => 'testGetByUsername',
1322 'last_name' => 'testGetByUsername',
1325 $ufMatchParams = array(
1326 'domain_id' => CRM_Core_Config
::domainID(),
1328 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
1329 'contact_id' => $cid,
1331 $ufMatch = CRM_Core_BAO_UFMatch
::create($ufMatchParams);
1332 $this->assertTrue(is_numeric($ufMatch->id
));
1334 // setup - mock the calls to CRM_Utils_System_*::getUfId
1335 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1336 $userSystem->expects($this->once())
1338 ->with($this->equalTo('exampleUser'))
1339 ->will($this->returnValue(99));
1340 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1343 $result = $this->callAPISuccess('Contact', 'get', array(
1344 'id' => '@user:exampleUser',
1346 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
1350 * Test to check return works OK
1352 public function testContactGetReturnValues() {
1353 $extraParams = array('nick_name' => 'Bob', 'phone' => '456', 'email' => 'e@mail.com');
1354 $contactID = $this->individualCreate($extraParams);
1355 //actually it turns out the above doesn't create a phone
1356 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
1357 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
1358 foreach ($extraParams as $key => $value) {
1359 $this->assertEquals($result[$key], $value);
1361 //now we check they are still returned with 'return' key
1362 $result = $this->callAPISuccess('contact', 'getsingle', array(
1364 'return' => array_keys($extraParams),
1366 foreach ($extraParams as $key => $value) {
1367 $this->assertEquals($result[$key], $value);
1371 public function testCRM13252MultipleChainedPhones() {
1372 $contactID = $this->householdCreate();
1373 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
1375 'contact_id' => $contactID,
1376 'household_name' => 'Household 1',
1377 'contact_type' => 'Household',
1378 'api.phone.create' => array(
1380 'phone' => '111-111-1111',
1381 'location_type_id' => 1,
1382 'phone_type_id' => 1,
1385 'phone' => '222-222-2222',
1386 'location_type_id' => 1,
1387 'phone_type_id' => 2,
1391 $this->callAPISuccess('contact', 'create', $params);
1392 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
1397 * Test for Contact.get id=@user:username (with an invalid username)
1399 public function testContactGetByUnknownUsername() {
1400 // setup - mock the calls to CRM_Utils_System_*::getUfId
1401 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1402 $userSystem->expects($this->once())
1404 ->with($this->equalTo('exampleUser'))
1405 ->will($this->returnValue(NULL));
1406 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1409 $result = $this->callAPIFailure('Contact', 'get', array(
1410 'id' => '@user:exampleUser',
1412 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
1416 * Verify attempt to create individual with chained arrays
1418 public function testGetIndividualWithChainedArrays() {
1419 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1420 $params['custom_' . $ids['custom_field_id']] = "custom string";
1422 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1423 $description = "/*this demonstrates the usage of chained api functions. In this case no notes or custom fields have been created ";
1424 $subfile = "APIChainedArray";
1426 'first_name' => 'abc3',
1427 'last_name' => 'xyz3',
1428 'contact_type' => 'Individual',
1429 'email' => 'man3@yahoo.com',
1430 'api.contribution.create' => array(
1431 'receive_date' => '2010-01-01',
1432 'total_amount' => 100.00,
1433 'financial_type_id' => 1,
1434 'payment_instrument_id' => 1,
1435 'non_deductible_amount' => 10.00,
1436 'fee_amount' => 50.00,
1437 'net_amount' => 90.00,
1439 'invoice_id' => 67890,
1441 'contribution_status_id' => 1,
1443 'api.contribution.create.1' => array(
1444 'receive_date' => '2011-01-01',
1445 'total_amount' => 120.00,
1446 'financial_type_id' => $this->_financialTypeId
= 1,
1447 'payment_instrument_id' => 1,
1448 'non_deductible_amount' => 10.00,
1449 'fee_amount' => 50.00,
1450 'net_amount' => 90.00,
1452 'invoice_id' => 67830,
1454 'contribution_status_id' => 1,
1456 'api.website.create' => array(
1458 'url' => "http://civicrm.org",
1463 $result = $this->callAPISuccess('Contact', 'create', $params);
1465 'id' => $result['id'],
1466 'api.website.get' => array(),
1467 'api.Contribution.get' => array(
1468 'total_amount' => '120.00',
1470 'api.CustomValue.get' => 1,
1471 'api.Note.get' => 1,
1473 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1474 // delete the contact
1475 $this->callAPISuccess('contact', 'delete', $result);
1476 $this->customGroupDelete($ids['custom_group_id']);
1477 $this->customGroupDelete($moreIDs['custom_group_id']);
1478 $this->assertEquals(1, $result['id']);
1479 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
1480 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
1483 public function testGetIndividualWithChainedArraysFormats() {
1484 $description = "/*this demonstrates the usage of chained api functions. A variety of return formats are used. Note that no notes
1485 *custom fields or memberships exist";
1486 $subfile = "APIChainedArrayFormats";
1487 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1488 $params['custom_' . $ids['custom_field_id']] = "custom string";
1490 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1492 'first_name' => 'abc3',
1493 'last_name' => 'xyz3',
1494 'contact_type' => 'Individual',
1495 'email' => 'man3@yahoo.com',
1496 'api.contribution.create' => array(
1497 'receive_date' => '2010-01-01',
1498 'total_amount' => 100.00,
1499 'financial_type_id' => $this->_financialTypeId
,
1500 'payment_instrument_id' => 1,
1501 'non_deductible_amount' => 10.00,
1502 'fee_amount' => 50.00,
1503 'net_amount' => 90.00,
1505 'contribution_status_id' => 1,
1507 'api.contribution.create.1' => array(
1508 'receive_date' => '2011-01-01',
1509 'total_amount' => 120.00,
1510 'financial_type_id' => $this->_financialTypeId
,
1511 'payment_instrument_id' => 1,
1512 'non_deductible_amount' => 10.00,
1513 'fee_amount' => 50.00,
1514 'net_amount' => 90.00,
1516 'contribution_status_id' => 1,
1518 'api.website.create' => array(
1520 'url' => "http://civicrm.org",
1525 $result = $this->callAPISuccess('Contact', 'create', $params);
1527 'id' => $result['id'],
1528 'api.website.getValue' => array('return' => 'url'),
1529 'api.Contribution.getCount' => array(),
1530 'api.CustomValue.get' => 1,
1531 'api.Note.get' => 1,
1532 'api.Membership.getCount' => array(),
1534 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1535 $this->assertEquals(1, $result['id']);
1536 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
1537 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
1538 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
1540 $this->callAPISuccess('contact', 'delete', $result);
1541 $this->customGroupDelete($ids['custom_group_id']);
1542 $this->customGroupDelete($moreIDs['custom_group_id']);
1546 * Test complex chaining.
1548 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
1549 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1550 $params['custom_' . $ids['custom_field_id']] = "custom string";
1551 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
1552 $andMoreIDs = $this->CustomGroupMultipleCreateWithFields(array(
1553 'title' => "another group",
1554 'name' => 'another name',
1556 $description = "/*this demonstrates the usage of chained api functions. A variety of techniques are used";
1557 $subfile = "APIChainedArrayMultipleCustom";
1559 'first_name' => 'abc3',
1560 'last_name' => 'xyz3',
1561 'contact_type' => 'Individual',
1562 'email' => 'man3@yahoo.com',
1563 'api.contribution.create' => array(
1564 'receive_date' => '2010-01-01',
1565 'total_amount' => 100.00,
1566 'financial_type_id' => 1,
1567 'payment_instrument_id' => 1,
1568 'non_deductible_amount' => 10.00,
1569 'fee_amount' => 50.00,
1570 'net_amount' => 90.00,
1572 'invoice_id' => 67890,
1574 'contribution_status_id' => 1,
1576 'api.contribution.create.1' => array(
1577 'receive_date' => '2011-01-01',
1578 'total_amount' => 120.00,
1579 'financial_type_id' => 1,
1580 'payment_instrument_id' => 1,
1581 'non_deductible_amount' => 10.00,
1582 'fee_amount' => 50.00,
1583 'net_amount' => 90.00,
1585 'invoice_id' => 67830,
1587 'contribution_status_id' => 1,
1589 'api.website.create' => array(
1591 'url' => "http://civicrm.org",
1594 'custom_' . $ids['custom_field_id'] => "value 1",
1595 'custom_' . $moreIDs['custom_field_id'][0] => "value 2",
1596 'custom_' . $moreIDs['custom_field_id'][1] => "warm beer",
1597 'custom_' . $andMoreIDs['custom_field_id'][1] => "vegemite",
1600 $result = $this->callAPISuccess('Contact', 'create', $params);
1601 $result = $this->callAPISuccess('Contact', 'create', array(
1602 'contact_type' => 'Individual',
1603 'id' => $result['id'],
1605 $moreIDs['custom_field_id'][0] => "value 3",
1607 $ids['custom_field_id'] => "value 4",
1611 'id' => $result['id'],
1612 'api.website.getValue' => array('return' => 'url'),
1613 'api.Contribution.getCount' => array(),
1614 'api.CustomValue.get' => 1,
1616 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1618 $this->customGroupDelete($ids['custom_group_id']);
1619 $this->customGroupDelete($moreIDs['custom_group_id']);
1620 $this->customGroupDelete($andMoreIDs['custom_group_id']);
1621 $this->assertEquals(1, $result['id']);
1622 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
1623 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
1627 * Test checks usage of $values to pick & choose inputs.
1629 public function testChainingValuesCreate() {
1630 $description = "/*this demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
1631 2 child functions - one receives values from the parent (Contact) and the other child (Tag). ";
1632 $subfile = "APIChainedArrayValuesFromSiblingFunction";
1634 'display_name' => 'batman',
1635 'contact_type' => 'Individual',
1636 'api.tag.create' => array('name' => '$value.id', 'description' => '$value.display_name', 'format.only_id' => 1),
1637 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
1639 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1640 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
1642 $tablesToTruncate = array(
1645 'civicrm_entity_tag',
1648 $this->quickCleanup($tablesToTruncate, TRUE);
1652 * Test TrueFalse format - I couldn't come up with an easy way to get an error on Get
1654 public function testContactGetFormatIsSuccessTrue() {
1655 $this->createContactFromXML();
1656 $description = "This demonstrates use of the 'format.is_success' param.
1657 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1658 $subfile = "FormatIsSuccess_True";
1659 $params = array('id' => 17, 'format.is_success' => 1);
1660 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1661 $this->assertEquals(1, $result);
1662 $this->callAPISuccess('Contact', 'Delete', $params);
1666 * test TrueFalse format
1668 public function testContactCreateFormatIsSuccessFalse() {
1670 $description = "This demonstrates use of the 'format.is_success' param.
1671 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1672 $subfile = "FormatIsSuccess_Fail";
1673 $params = array('id' => 500, 'format.is_success' => 1);
1674 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1675 $this->assertEquals(0, $result);
1679 * test Single Entity format
1681 public function testContactGetSingle_entity_array() {
1682 $this->createContactFromXML();
1683 $description = "This demonstrates use of the 'format.single_entity_array' param.
1684 /* This param causes the only contact to be returned as an array without the other levels.
1685 /* it will be ignored if there is not exactly 1 result";
1686 $subfile = "GetSingleContact";
1687 $params = array('id' => 17);
1688 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1689 $this->assertEquals('Test Contact', $result['display_name']);
1690 $this->callAPISuccess('Contact', 'Delete', $params);
1694 * Test Single Entity format.
1696 public function testContactGetFormatCount_only() {
1697 $this->createContactFromXML();
1698 $description = "This demonstrates use of the 'getCount' action.\n"
1700 . " * This param causes the count of the only function to be returned as an integer.";
1701 $subfile = "GetCountContact";
1702 $params = array('id' => 17);
1703 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__
, __FILE__
, $description,
1704 $subfile, 'getcount');
1705 $this->assertEquals('1', $result);
1706 $this->callAPISuccess('Contact', 'Delete', $params);
1710 * Test id only format.
1712 public function testContactGetFormatID_only() {
1713 $this->createContactFromXML();
1714 $description = "This demonstrates use of the 'format.id_only' param.
1715 /* This param causes the id of the only entity to be returned as an integer.
1716 /* it will be ignored if there is not exactly 1 result";
1717 $subfile = "FormatOnlyID";
1718 $params = array('id' => 17, 'format.only_id' => 1);
1719 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1720 $this->assertEquals('17', $result);
1721 $this->callAPISuccess('Contact', 'Delete', $params);
1725 * Test id only format.
1727 public function testContactGetFormatSingleValue() {
1728 $this->createContactFromXML();
1729 $description = "This demonstrates use of the 'format.single_value' param.
1730 /* This param causes only a single value of the only entity to be returned as an string.
1731 /* it will be ignored if there is not exactly 1 result";
1732 $subFile = "FormatSingleValue";
1733 $params = array('id' => 17, 'return' => 'display_name');
1734 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__
, __FILE__
, $description, $subFile, 'getvalue');
1735 $this->assertEquals('Test Contact', $result);
1736 $this->callAPISuccess('Contact', 'Delete', $params);
1740 * Test that permissions are respected when creating contacts.
1742 public function testContactCreationPermissions() {
1744 'contact_type' => 'Individual',
1745 'first_name' => 'Foo',
1746 'last_name' => 'Bear',
1747 'check_permissions' => TRUE,
1749 $config = CRM_Core_Config
::singleton();
1750 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1751 $result = $this->callAPIFailure('contact', 'create', $params);
1752 $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');
1754 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'add contacts', 'import contacts');
1755 $this->callAPISuccess('contact', 'create', $params, NULL, 'overfluous permissions should be enough to create a contact');
1759 * Test update with check permissions set.
1761 public function testContactUpdatePermissions() {
1763 'contact_type' => 'Individual',
1764 'first_name' => 'Foo',
1765 'last_name' => 'Bear',
1766 'check_permissions' => TRUE,
1768 $result = $this->callAPISuccess('contact', 'create', $params);
1769 $config = CRM_Core_Config
::singleton();
1771 'id' => $result['id'],
1772 'contact_type' => 'Individual',
1773 'last_name' => 'Bar',
1774 'check_permissions' => TRUE,
1777 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1778 $result = $this->callAPIFailure('contact', 'update', $params);
1779 $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');
1781 $config->userPermissionClass
->permissions
= array(
1784 'view all contacts',
1785 'edit all contacts',
1788 $this->callAPISuccess('contact', 'update', $params, NULL, 'overfluous permissions should be enough to update a contact');
1792 * Set up helper to create a contact.
1794 public function createContactFromXML() {
1795 // Insert a row in civicrm_contact creating contact 17.
1796 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1797 $op->execute($this->_dbconn
,
1798 $this->createXMLDataSet(
1799 dirname(__FILE__
) . '/dataset/contact_17.xml'
1805 * Test contact proximity api.
1807 public function testContactProximity() {
1808 // first create a contact with a SF location with a specific
1810 $contactID = $this->organizationCreate();
1812 // now create the address
1814 'street_address' => '123 Main Street',
1815 'city' => 'San Francisco',
1817 'country_id' => 1228,
1818 'state_province_id' => 1004,
1819 'geo_code_1' => '37.79',
1820 'geo_code_2' => '-122.40',
1821 'location_type_id' => 1,
1822 'contact_id' => $contactID,
1825 $result = $this->callAPISuccess('address', 'create', $params);
1826 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1828 // now do a proximity search with a close enough geocode and hope to match
1829 // that specific contact only!
1830 $proxParams = array(
1832 'longitude' => -122.3,
1836 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
1837 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1841 * Test that Ajax API permission is sufficient to access getquick api.
1843 * (note that getquick api is required for autocomplete & has ACL permissions applied)
1845 public function testGetquickPermission_CRM_13744() {
1846 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviEvent');
1847 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1848 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
1849 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1850 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access AJAX API');
1851 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1855 * Test get ref api - gets a list of references to an entity.
1857 public function testGetReferenceCounts() {
1858 $result = $this->callAPISuccess('Contact', 'create', array(
1859 'first_name' => 'Testily',
1860 'last_name' => 'McHaste',
1861 'contact_type' => 'Individual',
1862 'api.Address.replace' => array(
1863 'values' => array(),
1865 'api.Email.replace' => array(
1868 'email' => 'spam@dev.null',
1870 'location_type_id' => 1,
1874 'api.Phone.replace' => array(
1877 'phone' => '234-567-0001',
1879 'location_type_id' => 1,
1882 'phone' => '234-567-0002',
1884 'location_type_id' => 1,
1890 //$dao = new CRM_Contact_BAO_Contact();
1891 //$dao->id = $result['id'];
1892 //$this->assertTrue((bool) $dao->find(TRUE));
1894 //$refCounts = $dao->getReferenceCounts();
1895 //$this->assertTrue(is_array($refCounts));
1896 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
1898 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
1899 'id' => $result['id'],
1901 $refCountsIdx = CRM_Utils_Array
::index(array('name'), $refCounts['values']);
1903 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
1904 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
1905 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
1906 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
1907 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
1910 public function testSQLOperatorsOnContactAPI() {
1911 $this->individualCreate();
1912 $this->organizationCreate();
1913 $this->householdCreate();
1914 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
1915 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
1916 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
1917 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
1921 * CRM-14743 - test api respects search operators
1923 public function testGetModifiedDateByOperators() {
1924 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1925 $contact1 = $this->individualCreate();
1926 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
1927 CRM_Core_DAO
::executeQuery($sql);
1928 $contact2 = $this->individualCreate();
1929 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
1930 CRM_Core_DAO
::executeQuery($sql);
1931 $contact3 = $this->householdCreate();
1932 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
1933 CRM_Core_DAO
::executeQuery($sql);
1934 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
1935 $this->assertEquals($contacts['count'], 3);
1936 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
1937 $this->assertEquals($contacts['count'], $preExistingContactCount);
1941 * CRM-14743 - test api respects search operators
1943 public function testGetCreatedDateByOperators() {
1944 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1945 $contact1 = $this->individualCreate();
1946 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
1947 CRM_Core_DAO
::executeQuery($sql);
1948 $contact2 = $this->individualCreate();
1949 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
1950 CRM_Core_DAO
::executeQuery($sql);
1951 $contact3 = $this->householdCreate();
1952 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
1953 CRM_Core_DAO
::executeQuery($sql);
1954 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
1955 $this->assertEquals($contacts['count'], 3);
1956 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
1957 $this->assertEquals($contacts['count'], $preExistingContactCount);
1961 * CRM-14263 check that API is not affected by search profile related bug
1963 public function testReturnCityProfile() {
1964 $contactID = $this->individualCreate();
1965 CRM_Core_Config
::singleton()->defaultSearchProfileID
= 1;
1966 $this->callAPISuccess('address', 'create', array(
1967 'contact_id' => $contactID,
1968 'city' => 'Cool City',
1969 'location_type_id' => 1,
1971 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
1972 $this->assertEquals(1, $result['count']);
1976 * CRM-15443 - ensure getlist api does not return deleted contacts
1978 public function testGetlistExcludeConditions() {
1979 $name = md5(time());
1980 $contact = $this->individualCreate(array('last_name' => $name));
1981 $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
1982 $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
1983 // We should get all but the deleted contact.
1984 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
1985 $this->assertEquals(2, $result['count'], 'In line ' . __LINE__
);
1986 // Force-exclude the deceased contact.
1987 $result = $this->callAPISuccess('contact', 'getlist', array(
1989 'params' => array('is_deceased' => 0),
1991 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1992 $this->assertEquals($contact, $result['values'][0]['id'], 'In line ' . __LINE__
);
1996 * Test contact.getactions
1998 public function testGetActions() {
1999 $description = "Getting the available actions for an entity.";
2000 $result = $this->callAPIAndDocument($this->_entity
, 'getactions', array(), __FUNCTION__
, __FILE__
, $description);
2020 $deprecated = array(
2024 foreach ($expected as $action) {
2025 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
2027 foreach ($deprecated as $action) {
2028 $this->assertArrayKeyExists($action, $result['deprecated']);