3 * File for the TestContact class
7 * @author Walt Haas <walt@dharmatech.org> (801) 534-1262
8 * @copyright Copyright CiviCRM LLC (C) 2009
9 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html
10 * GNU Affero General Public License version 3
11 * @version $Id: ContactTest.php 31254 2010-12-15 10:09:29Z eileen $
14 * This file is part of CiviCRM
16 * CiviCRM is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Affero General Public License
18 * as published by the Free Software Foundation; either version 3 of
19 * the License, or (at your option) any later version.
21 * CiviCRM is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU Affero General Public License for more details.
26 * You should have received a copy of the GNU Affero General Public
27 * License along with this program. If not, see
28 * <http://www.gnu.org/licenses/>.
32 * Include class definitions
34 require_once 'CiviTest/CiviUnitTestCase.php';
38 * Test APIv3 civicrm_contact* functions
40 * @package CiviCRM_APIv3
41 * @subpackage API_Contact
43 class api_v3_ContactTest
extends CiviUnitTestCase
{
44 public $DBResetRequired = FALSE;
45 protected $_apiversion;
49 protected $_contactID;
50 protected $_financialTypeId = 1;
53 * Test setup for every test
55 * Connect to the database, truncate the tables that will be used
56 * and redirect stdin to a temporary file
58 public function setUp() {
59 // Connect to the database
61 $this->_apiversion
= 3;
62 $this->_entity
= 'contact';
63 $this->_params
= array(
64 'first_name' => 'abc1',
65 'contact_type' => 'Individual',
66 'last_name' => 'xyz1',
70 public function tearDown() {
71 // truncate a few tables
72 $tablesToTruncate = array(
75 'civicrm_contribution',
78 'civicrm_relationship',
83 $this->quickCleanup($tablesToTruncate, TRUE);
87 * Test civicrm_contact_create
89 * Verify that attempt to create individual contact with only
90 * first and last names succeeds
92 public function testAddCreateIndividual() {
93 $oldCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
95 'first_name' => 'abc1',
96 'contact_type' => 'Individual',
97 'last_name' => 'xyz1',
100 $contact = $this->callAPISuccess('contact', 'create', $params);
101 $this->assertTrue(is_numeric($contact['id']), "In line " . __LINE__
);
102 $this->assertTrue($contact['id'] > 0, "In line " . __LINE__
);
103 $newCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
104 $this->assertEquals($oldCount +
1, $newCount);
106 $this->assertDBState('CRM_Contact_DAO_Contact',
113 * Test civicrm_contact_create with sub-types
115 * Verify that sub-types are created successfully and not deleted by subsequent updates
117 public function testIndividualSubType() {
119 'first_name' => 'test abc',
120 'contact_type' => 'Individual',
121 'last_name' => 'test xyz',
122 'contact_sub_type' => array('Student', 'Staff'),
124 $contact = $this->callAPISuccess('contact', 'create', $params);
125 $cid = $contact['id'];
129 'middle_name' => 'foo',
131 $this->callAPISuccess('contact', 'create', $params);
132 unset($params['middle_name']);
134 $contact = $this->callAPISuccess('contact', 'get', $params);
136 $this->assertEquals(array('Student', 'Staff'), $contact['values'][$cid]['contact_sub_type'], "In line " . __LINE__
);
140 * Verify that attempt to create contact with empty params fails
142 public function testCreateEmptyContact() {
143 $this->callAPIFailure('contact', 'create', array());
147 * Verify that attempt to create contact with bad contact type fails
149 public function testCreateBadTypeContact() {
151 'email' => 'man1@yahoo.com',
152 'contact_type' => 'Does not Exist',
154 $this->callAPIFailure('contact', 'create', $params, "'Does not Exist' is not a valid option for field contact_type");
158 * Verify that attempt to create individual contact with required
159 * fields missing 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 with required
171 * fields missing fails
173 public function testCreateBadRequiredFieldsHousehold() {
175 'middle_name' => 'This field is not required',
176 'contact_type' => 'Household',
178 $this->callAPIFailure('contact', 'create', $params);
182 * Verify that attempt to create organization contact with
183 * required fields missing 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
198 public function testCreateEmailIndividual() {
201 'email' => 'man3@yahoo.com',
202 'contact_type' => 'Individual',
203 'location_type_id' => 1,
206 $contact = $this->callAPISuccess('contact', 'create', $params);
208 $this->assertEquals(1, $contact['id'], "In line " . __LINE__
);
209 $email = $this->callAPISuccess('email', 'get', array('contact_id' => $contact['id']));
210 $this->assertEquals(1, $email['count']);
211 $this->assertEquals('man3@yahoo.com', $email['values'][$email['id']]['email']);
213 $this->callAPISuccess('contact', 'delete', $contact);
217 * Verify that attempt to create individual contact with only
218 * 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 * Verify that attempt to create individual contact with
233 * first and last names and old key values works
235 public function testCreateNameIndividualOldKeys() {
237 'individual_prefix' => 'Dr.',
238 'first_name' => 'abc1',
239 'contact_type' => 'Individual',
240 'last_name' => 'xyz1',
241 'individual_suffix' => 'Jr.',
244 $contact = $this->callAPISuccess('contact', 'create', $params);
245 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
247 $this->assertArrayKeyExists('prefix_id', $result);
248 $this->assertArrayKeyExists('suffix_id', $result);
249 $this->assertArrayKeyExists('gender_id', $result);
250 $this->assertEquals(4, $result['prefix_id']);
251 $this->assertEquals(1, $result['suffix_id']);
255 * Verify that attempt to create individual contact with
256 * first and last names and old key values works
258 public function testCreateNameIndividualrecommendedKeys2() {
260 'prefix_id' => 'Dr.',
261 'first_name' => 'abc1',
262 'contact_type' => 'Individual',
263 'last_name' => 'xyz1',
264 'suffix_id' => 'Jr.',
265 'gender_id' => 'Male',
268 $contact = $this->callAPISuccess('contact', 'create', $params);
269 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
271 $this->assertArrayKeyExists('prefix_id', $result);
272 $this->assertArrayKeyExists('suffix_id', $result);
273 $this->assertArrayKeyExists('gender_id', $result);
274 $this->assertEquals(4, $result['prefix_id']);
275 $this->assertEquals(1, $result['suffix_id']);
279 * Verify that attempt to create household contact with only
280 * household name succeeds
282 public function testCreateNameHousehold() {
284 'household_name' => 'The abc Household',
285 'contact_type' => 'Household',
287 $contact = $this->callAPISuccess('contact', 'create', $params);
288 $this->assertEquals(1, $contact['id'], "In line " . __LINE__
);
292 * Verify that attempt to create organization contact with only
293 * organization name succeeds
295 public function testCreateNameOrganization() {
297 'organization_name' => 'The abc Organization',
298 'contact_type' => 'Organization',
300 $contact = $this->callAPISuccess('contact', 'create', $params);
301 $this->assertEquals(1, $contact['id']);
305 * Verify that attempt to create organization contact without organization name fails
307 public function testCreateNoNameOrganization() {
309 'first_name' => 'The abc Organization',
310 'contact_type' => 'Organization',
312 $this->callAPIFailure('contact', 'create', $params);
316 * Check with complete array + custom field
317 * Note that the test is written on purpose without any
318 * variables specific to participant so it can be replicated into other entities
319 * and / or moved to the automated test suite
321 public function testCreateWithCustom() {
322 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
324 $params = $this->_params
;
325 $params['custom_' . $ids['custom_field_id']] = "custom string";
326 $description = "/*this demonstrates setting a custom field through the API ";
327 $result = $this->callAPIAndDocument($this->_entity
, 'create', $params, __FUNCTION__
, __FILE__
, $description);
329 $check = $this->callAPISuccess($this->_entity
, 'get', array(
330 'return.custom_' . $ids['custom_field_id'] => 1,
331 'id' => $result['id'],
333 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
335 $this->customFieldDelete($ids['custom_field_id']);
336 $this->customGroupDelete($ids['custom_group_id']);
340 * CRM-12773 - expectation is that civicrm quietly ignores
341 * fields without values
343 public function testCreateWithNULLCustomCRM12773() {
344 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
345 $params = $this->_params
;
346 $params['custom_' . $ids['custom_field_id']] = NULL;
347 $this->callAPISuccess('contact', 'create', $params);
348 $this->customFieldDelete($ids['custom_field_id']);
349 $this->customGroupDelete($ids['custom_group_id']);
354 * Test creating a current employer through API
356 public function testContactCreateCurrentEmployer() {
357 //here we will just do the get for set-up purposes
358 $count = $this->callAPISuccess('contact', 'getcount', array(
359 'organization_name' => 'new employer org',
360 'contact_type' => 'Organization',
362 $this->assertEquals(0, $count);
363 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
364 'current_employer' => 'new employer org',
367 // do it again as an update to check it doesn't cause an error
368 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
369 'current_employer' => 'new employer org',
370 'id' => $employerResult['id'],
374 $this->callAPISuccess('contact', 'getcount', array(
375 'organization_name' => 'new employer org',
376 'contact_type' => 'Organization',
380 $result = $this->callAPISuccess('contact', 'getsingle', array(
381 'id' => $employerResult['id'],
384 $this->assertEquals('new employer org', $result['current_employer']);
389 * Test creating a current employer through API
390 * - check it will re-activate a de-activated employer
392 public function testContactCreateDuplicateCurrentEmployerEnables() {
393 //set up - create employer relationship
394 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
395 'current_employer' => 'new employer org',
398 $relationship = $this->callAPISuccess('relationship', 'get', array(
399 'contact_id_a' => $employerResult['id'],
402 //disable & check it is disabled
403 $this->callAPISuccess('relationship', 'create', array('id' => $relationship['id'], 'is_active' => 0));
404 $this->callAPISuccess('relationship', 'getvalue', array(
405 'id' => $relationship['id'],
406 'return' => 'is_active',
409 //re-set the current employer - thus enabling the relationshp
410 $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
411 'current_employer' => 'new employer org',
412 'id' => $employerResult['id'],
415 //check is_active is now 1
416 $relationship = $this->callAPISuccess('relationship', 'getsingle', array(
417 'return' => 'is_active',
419 $this->assertEquals(1, $relationship['is_active']);
423 * Check deceased contacts are not retrieved
424 * Note at time of writing the default is to return default. This should possibly be changed & test added
426 public function testGetDeceasedRetrieved() {
427 $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
428 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
429 'first_name' => 'bb',
430 'last_name' => 'ccc',
431 'contact_type' => 'Individual',
434 $result = $this->callAPISuccess($this->_entity
, 'get', array('is_deceased' => 0));
435 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
439 * Test that sort works - old syntax
441 public function testGetSort() {
442 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
443 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
444 'first_name' => 'bb',
445 'last_name' => 'ccc',
446 'contact_type' => 'Individual',
448 $result = $this->callAPISuccess($this->_entity
, 'get', array(
449 'sort' => 'first_name ASC',
450 'return.first_name' => 1,
455 $this->assertEquals('abc1', $result['values'][0]['first_name']);
456 $result = $this->callAPISuccess($this->_entity
, 'get', array(
457 'sort' => 'first_name DESC',
458 'return.first_name' => 1,
462 $this->assertEquals('bb', $result['values'][0]['first_name']);
464 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
465 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
469 * Test that we can retrieve contacts using
470 * 'id' => array('IN' => array('3,4')) syntax
472 public function testGetINIDArray() {
473 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
474 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
475 'first_name' => 'bb',
476 'last_name' => 'ccc',
477 'contact_type' => 'Individual',
479 $c3 = $this->callAPISuccess($this->_entity
, 'create', array(
480 'first_name' => 'hh',
482 'contact_type' => 'Individual',
484 $result = $this->callAPISuccess($this->_entity
, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
485 $this->assertEquals(2, $result['count']);
486 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
487 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
488 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
489 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c3['id']));
493 * Test variants on deleted behaviour
495 public function testGetDeleted() {
496 $params = $this->_params
;
497 $contact1 = $this->callAPISuccess('contact', 'create', $params);
498 $params['is_deleted'] = 1;
499 $params['last_name'] = 'bcd';
500 $contact2 = $this->callAPISuccess('contact', 'create', $params);
501 $countActive = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'active'));
502 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all'));
503 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash'));
504 $countDefault = $this->callAPISuccess('contact', 'getcount', array());
505 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
506 'contact_is_deleted' => 1,
508 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
509 'contact_is_deleted' => 0,
511 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
512 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
513 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected in line ' . __LINE__
);
514 $this->assertEquals(1, $countActive, 'in line ' . __LINE__
);
515 $this->assertEquals(1, $countTrash, 'in line ' . __LINE__
);
516 $this->assertEquals(2, $countAll, 'in line ' . __LINE__
);
517 $this->assertEquals(1, $countDeleted, 'in line ' . __LINE__
);
518 $this->assertEquals(1, $countDefault, 'Only active by default in line ' . __LINE__
);
522 * Test that sort works - new syntax
524 public function testGetSortNewSYntax() {
525 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
526 $c2 = $this->callAPISuccess($this->_entity
, 'create', array(
527 'first_name' => 'bb',
528 'last_name' => 'ccc',
529 'contact_type' => 'Individual',
531 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
532 'return' => 'first_name',
535 'sort' => 'first_name',
538 $this->assertEquals('abc1', $result, 'in line' . __LINE__
);
540 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
541 'return' => 'first_name',
544 'sort' => 'first_name DESC',
547 $this->assertEquals('bb', $result);
549 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
550 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
554 * Test apostrophe works in get & create
556 public function testGetApostropheCRM10857() {
557 $params = array_merge($this->_params
, array('last_name' => "O'Connor"));
558 $this->callAPISuccess($this->_entity
, 'create', $params);
559 $result = $this->callAPISuccess($this->_entity
, 'getsingle', array(
560 'last_name' => "O'Connor",
563 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__
);
567 * Check with complete array + custom field
568 * Note that the test is written on purpose without any
569 * variables specific to participant so it can be replicated into other entities
570 * and / or moved to the automated test suite
572 public function testGetWithCustom() {
573 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
575 $params = $this->_params
;
576 $params['custom_' . $ids['custom_field_id']] = "custom string";
577 $description = "/*this demonstrates setting a custom field through the API ";
578 $subfile = "CustomFieldGet";
579 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
581 $check = $this->callAPIAndDocument($this->_entity
, 'get', array(
582 'return.custom_' . $ids['custom_field_id'] => 1,
583 'id' => $result['id'],
584 ), __FUNCTION__
, __FILE__
, $description, $subfile);
586 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
587 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
588 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
589 $this->customFieldDelete($ids['custom_field_id']);
590 $this->customGroupDelete($ids['custom_group_id']);
594 * Check with complete array + custom field
595 * Note that the test is written on purpose without any
596 * variables specific to participant so it can be replicated into other entities
597 * and / or moved to the automated test suite
599 public function testGetWithCustomReturnSyntax() {
600 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
602 $params = $this->_params
;
603 $params['custom_' . $ids['custom_field_id']] = "custom string";
604 $description = "/*this demonstrates setting a custom field through the API ";
605 $subfile = "CustomFieldGetReturnSyntaxVariation";
606 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
607 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
608 $check = $this->callAPIAndDocument($this->_entity
, 'get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
610 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
611 $this->customFieldDelete($ids['custom_field_id']);
612 $this->customGroupDelete($ids['custom_group_id']);
616 * Check that address name is returned if required
618 public function testGetReturnAddressName() {
619 $contactID = $this->individualCreate();
620 $this->callAPISuccess('address', 'create', array(
621 'contact_id' => $contactID,
622 'address_name' => 'My house',
623 'location_type_id' => 'Home',
624 'street_address' => '1 my road',
626 $result = $this->callAPISuccessGetSingle('contact', array(
627 'return' => 'address_name, street_address',
630 $this->assertEquals('1 my road', $result['street_address']);
631 $this->assertEquals('My house', $result['address_name']);
635 public function testGetGroupIDFromContact() {
636 $groupId = $this->groupCreate();
637 $description = "Get all from group and display contacts";
638 $subFile = "GroupFilterUsingContactAPI";
640 'email' => 'man2@yahoo.com',
641 'contact_type' => 'Individual',
642 'location_type_id' => 1,
643 'api.group_contact.create' => array('group_id' => $groupId),
646 $this->callAPISuccess('contact', 'create', $params);
647 // testing as integer
649 'filter.group_id' => $groupId,
650 'contact_type' => 'Individual',
652 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
653 $this->assertEquals(1, $result['count']);
654 // group 26 doesn't exist, but we can still search contacts in it.
656 'filter.group_id' => 26,
657 'contact_type' => 'Individual',
659 $this->callAPISuccess('contact', 'get', $params);
662 'filter.group_id' => "$groupId, 26",
663 'contact_type' => 'Individual',
665 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
666 $this->assertEquals(1, $result['count']);
668 'filter.group_id' => "26,27",
669 'contact_type' => 'Individual',
671 $this->callAPISuccess('contact', 'get', $params);
675 'filter.group_id' => array($groupId, 26),
676 'contact_type' => 'Individual',
678 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
679 $this->assertEquals(1, $result['count']);
681 //test in conjunction with other criteria
683 'filter.group_id' => array($groupId, 26),
684 'contact_type' => 'Organization',
686 $this->callAPISuccess('contact', 'get', $params);
688 'filter.group_id' => array(26, 27),
689 'contact_type' => 'Individual',
691 $result = $this->callAPISuccess('contact', 'get', $params);
692 $this->assertEquals(0, $result['count']);
696 * Verify that attempt to create individual contact with two chained websites succeeds
698 public function testCreateIndividualWithContributionDottedSyntax() {
699 $description = "test demonstrates the syntax to create 2 chained entities";
700 $subFile = "ChainTwoWebsites";
702 'first_name' => 'abc3',
703 'last_name' => 'xyz3',
704 'contact_type' => 'Individual',
705 'email' => 'man3@yahoo.com',
706 'api.contribution.create' => array(
707 'receive_date' => '2010-01-01',
708 'total_amount' => 100.00,
709 'financial_type_id' => $this->_financialTypeId
,
710 'payment_instrument_id' => 1,
711 'non_deductible_amount' => 10.00,
712 'fee_amount' => 50.00,
713 'net_amount' => 90.00,
715 'invoice_id' => 67990,
717 'contribution_status_id' => 1,
719 'api.website.create' => array(
720 'url' => "http://civicrm.org",
722 'api.website.create.2' => array(
723 'url' => "http://chained.org",
727 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
729 $this->assertEquals(1, $result['id'], "In line " . __LINE__
);
730 // checking child function result not covered in callAPIAndDocument
731 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
732 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url'], "In line " . __LINE__
);
733 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url'], "In line " . __LINE__
);
735 // delete the contact
736 $this->callAPISuccess('contact', 'delete', $result);
740 * Verify that attempt to create individual contact with chained contribution and website succeeds
742 public function testCreateIndividualWithContributionChainedArrays() {
744 'first_name' => 'abc3',
745 'last_name' => 'xyz3',
746 'contact_type' => 'Individual',
747 'email' => 'man3@yahoo.com',
748 'api.contribution.create' => array(
749 'receive_date' => '2010-01-01',
750 'total_amount' => 100.00,
751 'financial_type_id' => $this->_financialTypeId
,
752 'payment_instrument_id' => 1,
753 'non_deductible_amount' => 10.00,
754 'fee_amount' => 50.00,
755 'net_amount' => 90.00,
757 'invoice_id' => 67890,
759 'contribution_status_id' => 1,
761 'api.website.create' => array(
763 'url' => "http://civicrm.org",
766 'url' => "http://chained.org",
767 'website_type_id' => 2,
772 $description = "demonstrates creating two websites as an array";
773 $subfile = "ChainTwoWebsitesSyntax2";
774 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
776 $this->assertEquals(1, $result['id']);
777 // the callAndDocument doesn't check the chained call
778 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error'], "In line " . __LINE__
);
779 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url'], "In line " . __LINE__
);
780 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url'], "In line " . __LINE__
);
782 $this->callAPISuccess('contact', 'delete', $result);
786 * Verify that attempt to create individual contact with first
787 * and last names and email succeeds
789 public function testCreateIndividualWithNameEmail() {
791 'first_name' => 'abc3',
792 'last_name' => 'xyz3',
793 'contact_type' => 'Individual',
794 'email' => 'man3@yahoo.com',
797 $contact = $this->callAPISuccess('contact', 'create', $params);
798 $this->assertEquals(1, $contact['id'], "In line " . __LINE__
);
800 // delete the contact
801 $this->callAPISuccess('contact', 'delete', $contact);
805 * Verify that attempt to create individual contact with no data fails
807 public function testCreateIndividualWithOutNameEmail() {
809 'contact_type' => 'Individual',
811 $this->callAPIFailure('contact', 'create', $params);
815 * Verify that attempt to create individual contact with first
816 * and last names, email and location type succeeds
818 public function testCreateIndividualWithNameEmailLocationType() {
820 'first_name' => 'abc4',
821 'last_name' => 'xyz4',
822 'email' => 'man4@yahoo.com',
823 'contact_type' => 'Individual',
824 'location_type_id' => 1,
826 $result = $this->callAPISuccess('contact', 'create', $params);
828 $this->assertEquals(1, $result['id'], "In line " . __LINE__
);
830 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
834 * Verify that when changing employers
835 * the old employer relationship becomes inactive
837 public function testCreateIndividualWithEmployer() {
838 $employer = $this->organizationCreate();
839 $employer2 = $this->organizationCreate();
842 'email' => 'man4@yahoo.com',
843 'contact_type' => 'Individual',
844 'employer_id' => $employer,
847 $result = $this->callAPISuccess('contact', 'create', $params);
848 $relationships = $this->callAPISuccess('relationship', 'get', array(
849 'contact_id_a' => $result['id'],
853 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
855 // Add more random relationships to make the test more realistic
856 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
857 $relTypeId = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
858 $this->callAPISuccess('relationship', 'create', array(
859 'contact_id_a' => $result['id'],
860 'contact_id_b' => $this->organizationCreate(),
862 'relationship_type_id' => $relTypeId,
866 // Add second employer
867 $params['employer_id'] = $employer2;
868 $params['id'] = $result['id'];
869 $result = $this->callAPISuccess('contact', 'create', $params);
871 $relationships = $this->callAPISuccess('relationship', 'get', array(
872 'contact_id_a' => $result['id'],
877 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
881 * Verify that attempt to create household contact with details
884 public function testCreateHouseholdDetails() {
886 'household_name' => 'abc8\'s House',
887 'nick_name' => 'x House',
888 'email' => 'man8@yahoo.com',
889 'contact_type' => 'Household',
892 $contact = $this->callAPISuccess('contact', 'create', $params);
894 $this->assertEquals(1, $contact['id'], "In line " . __LINE__
);
896 $this->callAPISuccess('contact', 'delete', $contact);
900 * Verify that attempt to create household contact with inadequate details
903 public function testCreateHouseholdInadequateDetails() {
905 'nick_name' => 'x House',
906 'email' => 'man8@yahoo.com',
907 'contact_type' => 'Household',
909 $this->callAPIFailure('contact', 'create', $params);
913 * Verify successful update of individual contact
915 public function testUpdateIndividualWithAll() {
916 // Insert a row in civicrm_contact creating individual contact
917 $op = new PHPUnit_Extensions_Database_Operation_Insert();
918 $op->execute($this->_dbconn
,
919 $this->createXMLDataSet(
920 dirname(__FILE__
) . '/dataset/contact_ind.xml'
926 'first_name' => 'abcd',
927 'contact_type' => 'Individual',
928 'nick_name' => 'This is nickname first',
929 'do_not_email' => '1',
930 'do_not_phone' => '1',
931 'do_not_mail' => '1',
932 'do_not_trade' => '1',
933 'legal_identifier' => 'ABC23853ZZ2235',
934 'external_identifier' => '1928837465',
935 'image_URL' => 'http://some.url.com/image.jpg',
936 'home_url' => 'http://www.example.org',
940 $this->callAPISuccess('Contact', 'Update', $params);
941 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
942 unset($params['contact_id']);
943 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
944 //reducing this test partially back to api v2 level to get it through
945 unset($params['home_url']);
946 foreach ($params as $key => $value) {
947 $this->assertEquals($value, $getResult['values'][23][$key]);
949 // Check updated civicrm_contact against expected
950 $expected = $this->createXMLDataSet(
951 dirname(__FILE__
) . '/dataset/contact_ind_upd.xml'
953 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
956 $actual->addTable('civicrm_contact');
957 $expected->matches($actual);
961 * Verify successful update of organization contact
963 public function testUpdateOrganizationWithAll() {
964 // Insert a row in civicrm_contact creating organization contact
965 $op = new PHPUnit_Extensions_Database_Operation_Insert();
966 $op->execute($this->_dbconn
,
967 $this->createXMLDataSet(
968 dirname(__FILE__
) . '/dataset/contact_org.xml'
974 'organization_name' => 'WebAccess India Pvt Ltd',
975 'legal_name' => 'WebAccess',
976 'sic_code' => 'ABC12DEF',
977 'contact_type' => 'Organization',
980 $this->callAPISuccess('Contact', 'Update', $params);
982 // Check updated civicrm_contact against expected
983 $expected = $this->createXMLDataSet(
984 dirname(__FILE__
) . '/dataset/contact_org_upd.xml'
986 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
989 $actual->addTable('civicrm_contact');
990 $expected->matches($actual);
994 * Verify successful update of household contact
996 public function testUpdateHouseholdwithAll() {
997 // Insert a row in civicrm_contact creating household contact
998 $op = new PHPUnit_Extensions_Database_Operation_Insert();
999 $op->execute($this->_dbconn
,
1000 $this->createXMLDataSet(
1001 dirname(__FILE__
) . '/dataset/contact_hld.xml'
1007 'household_name' => 'ABC household',
1008 'nick_name' => 'ABC House',
1009 'contact_type' => 'Household',
1012 $result = $this->callAPISuccess('Contact', 'Update', $params);
1015 'contact_type' => 'Household',
1017 'sort_name' => 'ABC household',
1018 'display_name' => 'ABC household',
1019 'nick_name' => 'ABC House',
1021 $this->getAndCheck($expected, $result['id'], 'contact');
1025 * Test civicrm_update() Deliberately exclude contact_type as it should still
1026 * cope using civicrm_api CRM-7645
1028 public function testUpdateCreateWithID() {
1029 // Insert a row in civicrm_contact creating individual contact
1030 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1031 $op->execute($this->_dbconn
,
1032 $this->createXMLDataSet(
1033 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1039 'first_name' => 'abcd',
1040 'last_name' => 'wxyz',
1042 $this->callAPISuccess('Contact', 'Update', $params);
1046 * Test civicrm_contact_delete() with no contact ID
1048 public function testContactDeleteNoID() {
1052 $this->callAPIFailure('contact', 'delete', $params);
1056 * Test civicrm_contact_delete() with error
1058 public function testContactDeleteError() {
1059 $params = array('contact_id' => 999);
1060 $this->callAPIFailure('contact', 'delete', $params);
1064 * Test civicrm_contact_delete()
1066 public function testContactDelete() {
1067 $contactID = $this->individualCreate();
1071 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__
, __FILE__
);
1075 * Test civicrm_contact_get() return only first name
1077 public function testContactGetRetFirst() {
1078 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1080 'contact_id' => $contact['id'],
1081 'return_first_name' => TRUE,
1082 'sort' => 'first_name',
1084 $result = $this->callAPISuccess('contact', 'get', $params);
1085 $this->assertEquals(1, $result['count']);
1086 $this->assertEquals($contact['id'], $result['id']);
1087 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1091 * Test civicrm_contact_get() return only first name & last name
1092 * Use comma separated string return with a space
1094 public function testContactGetRetFirstLast() {
1095 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1097 'contact_id' => $contact['id'],
1098 'return' => 'first_name, last_name',
1100 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1101 $this->assertEquals('abc1', $result['first_name']);
1102 $this->assertEquals('xyz1', $result['last_name']);
1103 //check that other defaults not returns
1104 $this->assertArrayNotHasKey('sort_name', $result);
1106 'contact_id' => $contact['id'],
1107 'return' => 'first_name,last_name',
1109 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1110 $this->assertEquals('abc1', $result['first_name']);
1111 $this->assertEquals('xyz1', $result['last_name']);
1112 //check that other defaults not returns
1113 $this->assertArrayNotHasKey('sort_name', $result);
1117 * Test civicrm_contact_get() return only first name & last name
1118 * Use comma separated string return without a space
1120 public function testContactGetRetFirstLastNoComma() {
1121 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1123 'contact_id' => $contact['id'],
1124 'return' => 'first_name,last_name',
1126 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1127 $this->assertEquals('abc1', $result['first_name']);
1128 $this->assertEquals('xyz1', $result['last_name']);
1129 //check that other defaults not returns
1130 $this->assertArrayNotHasKey('sort_name', $result);
1134 * Test civicrm_contact_get() with default return properties
1136 public function testContactGetRetDefault() {
1137 $contactID = $this->individualCreate();
1139 'contact_id' => $contactID,
1140 'sort' => 'first_name',
1142 $result = $this->callAPISuccess('contact', 'get', $params);
1143 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1144 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1148 * Test civicrm_contact_getquick() with empty name param
1150 public function testContactGetQuick() {
1151 // Insert a row in civicrm_contact creating individual contact
1152 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1153 $op->execute($this->_dbconn
,
1154 $this->createXMLDataSet(
1155 dirname(__FILE__
) . '/dataset/contact_17.xml'
1158 $op->execute($this->_dbconn
,
1159 $this->createXMLDataSet(
1160 dirname(__FILE__
) . '/dataset/email_contact_17.xml'
1167 $result = $this->callAPISuccess('contact', 'getquick', $params);
1168 $this->assertEquals(17, $result['values'][0]['id'], 'in line ' . __LINE__
);
1172 * Test civicrm_contact_get) with empty params
1174 public function testContactGetEmptyParams() {
1175 $this->callAPISuccess('contact', 'get', array());
1179 * Test civicrm_contact_get(,true) with no matches
1181 public function testContactGetOldParamsNoMatches() {
1182 // Insert a row in civicrm_contact creating contact 17
1183 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1184 $op->execute($this->_dbconn
,
1185 $this->createXMLDataSet(
1186 dirname(__FILE__
) . '/dataset/contact_17.xml'
1191 'first_name' => 'Fred',
1193 $result = $this->callAPISuccess('contact', 'get', $params);
1194 $this->assertEquals(0, $result['count'], 'in line ' . __LINE__
);
1198 * Test civicrm_contact_get(,true) with one match
1200 public function testContactGetOldParamsOneMatch() {
1201 // Insert a row in civicrm_contact creating contact 17
1202 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1203 $op->execute($this->_dbconn
,
1204 $this->createXMLDataSet(dirname(__FILE__
) . '/dataset/contact_17.xml'
1209 'first_name' => 'Test',
1211 $result = $this->callAPISuccess('contact', 'get', $params);
1212 $this->assertEquals(17, $result['values'][17]['contact_id'], 'in line ' . __LINE__
);
1213 $this->assertEquals(17, $result['id'], 'in line ' . __LINE__
);
1217 * Test civicrm_contact_search_count()
1219 public function testContactGetEmail() {
1221 'email' => 'man2@yahoo.com',
1222 'contact_type' => 'Individual',
1223 'location_type_id' => 1,
1226 $contact = $this->callAPISuccess('contact', 'create', $params);
1228 $this->assertEquals(1, $contact['id']);
1231 'email' => 'man2@yahoo.com',
1233 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
);
1234 $this->assertEquals(1, $result['values'][1]['contact_id']);
1235 $this->assertEquals('man2@yahoo.com', $result['values'][1]['email']);
1237 // delete the contact
1238 $this->callAPISuccess('contact', 'delete', $contact);
1242 * Test birth date params incl value, array & birth_date_high, birth_date_low
1245 public function testContactGetBirthDate() {
1246 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 2 years')));
1247 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 5 years')));
1248 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month -20 years')));
1250 $result = $this->callAPISuccess('contact', 'get', array());
1251 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1252 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1253 $this->assertEquals(1, $result['count']);
1254 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1255 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1256 $this->assertEquals(1, $result['count']);
1257 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1258 $result = $this->callAPISuccess('contact', 'get', array(
1259 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
1260 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
1262 $this->assertEquals(1, $result['count']);
1263 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1264 $result = $this->callAPISuccess('contact', 'get', array(
1265 'birth_date_low' => '-6 years',
1266 'birth_date_high' => '- 3 years',
1268 $this->assertEquals(1, $result['count']);
1269 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1273 * Test Deceaseddate params incl value, array & Deceased_date_high, Deceaseddate_low
1276 public function testContactGetDeceasedDate() {
1277 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 2 years')));
1278 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 5 years')));
1279 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month -20 years')));
1281 $result = $this->callAPISuccess('contact', 'get', array());
1282 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
1283 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
1284 $this->assertEquals(1, $result['count']);
1285 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1286 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
1287 $this->assertEquals(1, $result['count']);
1288 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
1289 $result = $this->callAPISuccess('contact', 'get', array(
1290 'deceased_date_low' => '-6 years',
1291 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
1293 $this->assertEquals(1, $result['count']);
1294 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1298 * Test for Contact.get id=@user:username
1300 public function testContactGetByUsername() {
1301 // setup - create contact with a uf-match
1302 $cid = $this->individualCreate(array(
1303 'contact_type' => 'Individual',
1304 'first_name' => 'testGetByUsername',
1305 'last_name' => 'testGetByUsername',
1308 $ufMatchParams = array(
1309 'domain_id' => CRM_Core_Config
::domainID(),
1311 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
1312 'contact_id' => $cid,
1314 $ufMatch = CRM_Core_BAO_UFMatch
::create($ufMatchParams);
1315 $this->assertTrue(is_numeric($ufMatch->id
));
1317 // setup - mock the calls to CRM_Utils_System_*::getUfId
1318 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1319 $userSystem->expects($this->once())
1321 ->with($this->equalTo('exampleUser'))
1322 ->will($this->returnValue(99));
1323 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1326 $result = $this->callAPISuccess('Contact', 'get', array(
1327 'id' => '@user:exampleUser',
1329 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
1333 * Test to check return works OK
1335 public function testContactGetReturnValues() {
1336 $extraParams = array('nick_name' => 'Bob', 'phone' => '456', 'email' => 'e@mail.com');
1337 $contactID = $this->individualCreate($extraParams);
1338 //actually it turns out the above doesn't create a phone
1339 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
1340 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
1341 foreach ($extraParams as $key => $value) {
1342 $this->assertEquals($result[$key], $value);
1344 //now we check they are still returned with 'return' key
1345 $result = $this->callAPISuccess('contact', 'getsingle', array(
1347 'return' => array_keys($extraParams),
1349 foreach ($extraParams as $key => $value) {
1350 $this->assertEquals($result[$key], $value);
1354 public function testCRM13252MultipleChainedPhones() {
1355 $contactID = $this->householdCreate();
1356 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
1358 'contact_id' => $contactID,
1359 'household_name' => 'Household 1',
1360 'contact_type' => 'Household',
1361 'api.phone.create' => array(
1363 'phone' => '111-111-1111',
1364 'location_type_id' => 1,
1365 'phone_type_id' => 1,
1368 'phone' => '222-222-2222',
1369 'location_type_id' => 1,
1370 'phone_type_id' => 2,
1374 $this->callAPISuccess('contact', 'create', $params);
1375 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
1380 * Test for Contact.get id=@user:username (with an invalid username)
1382 public function testContactGetByUnknownUsername() {
1383 // setup - mock the calls to CRM_Utils_System_*::getUfId
1384 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1385 $userSystem->expects($this->once())
1387 ->with($this->equalTo('exampleUser'))
1388 ->will($this->returnValue(NULL));
1389 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1392 $result = $this->callAPIFailure('Contact', 'get', array(
1393 'id' => '@user:exampleUser',
1395 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
1399 * Verify attempt to create individual with chained arrays
1401 public function testGetIndividualWithChainedArrays() {
1402 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1403 $params['custom_' . $ids['custom_field_id']] = "custom string";
1405 $moreids = $this->CustomGroupMultipleCreateWithFields();
1406 $description = "/*this demonstrates the usage of chained api functions. In this case no notes or custom fields have been created ";
1407 $subfile = "APIChainedArray";
1409 'first_name' => 'abc3',
1410 'last_name' => 'xyz3',
1411 'contact_type' => 'Individual',
1412 'email' => 'man3@yahoo.com',
1413 'api.contribution.create' => array(
1414 'receive_date' => '2010-01-01',
1415 'total_amount' => 100.00,
1416 'financial_type_id' => 1,
1417 'payment_instrument_id' => 1,
1418 'non_deductible_amount' => 10.00,
1419 'fee_amount' => 50.00,
1420 'net_amount' => 90.00,
1422 'invoice_id' => 67890,
1424 'contribution_status_id' => 1,
1426 'api.contribution.create.1' => array(
1427 'receive_date' => '2011-01-01',
1428 'total_amount' => 120.00,
1429 'financial_type_id' => $this->_financialTypeId
= 1,
1430 'payment_instrument_id' => 1,
1431 'non_deductible_amount' => 10.00,
1432 'fee_amount' => 50.00,
1433 'net_amount' => 90.00,
1435 'invoice_id' => 67830,
1437 'contribution_status_id' => 1,
1439 'api.website.create' => array(
1441 'url' => "http://civicrm.org",
1446 $result = $this->callAPISuccess('Contact', 'create', $params);
1448 'id' => $result['id'],
1449 'api.website.get' => array(),
1450 'api.Contribution.get' => array(
1451 'total_amount' => '120.00',
1453 'api.CustomValue.get' => 1,
1454 'api.Note.get' => 1,
1456 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1457 // delete the contact
1458 $this->callAPISuccess('contact', 'delete', $result);
1459 $this->customGroupDelete($ids['custom_group_id']);
1460 $this->customGroupDelete($moreids['custom_group_id']);
1461 $this->assertEquals(1, $result['id']);
1462 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
1463 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
1466 public function testGetIndividualWithChainedArraysFormats() {
1467 $description = "/*this demonstrates the usage of chained api functions. A variety of return formats are used. Note that no notes
1468 *custom fields or memberships exist";
1469 $subfile = "APIChainedArrayFormats";
1470 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1471 $params['custom_' . $ids['custom_field_id']] = "custom string";
1473 $moreids = $this->CustomGroupMultipleCreateWithFields();
1475 'first_name' => 'abc3',
1476 'last_name' => 'xyz3',
1477 'contact_type' => 'Individual',
1478 'email' => 'man3@yahoo.com',
1479 'api.contribution.create' => array(
1480 'receive_date' => '2010-01-01',
1481 'total_amount' => 100.00,
1482 'financial_type_id' => $this->_financialTypeId
,
1483 'payment_instrument_id' => 1,
1484 'non_deductible_amount' => 10.00,
1485 'fee_amount' => 50.00,
1486 'net_amount' => 90.00,
1488 'contribution_status_id' => 1,
1490 'api.contribution.create.1' => array(
1491 'receive_date' => '2011-01-01',
1492 'total_amount' => 120.00,
1493 'financial_type_id' => $this->_financialTypeId
,
1494 'payment_instrument_id' => 1,
1495 'non_deductible_amount' => 10.00,
1496 'fee_amount' => 50.00,
1497 'net_amount' => 90.00,
1499 'contribution_status_id' => 1,
1501 'api.website.create' => array(
1503 'url' => "http://civicrm.org",
1508 $result = $this->callAPISuccess('Contact', 'create', $params);
1510 'id' => $result['id'],
1511 'api.website.getValue' => array('return' => 'url'),
1512 'api.Contribution.getCount' => array(),
1513 'api.CustomValue.get' => 1,
1514 'api.Note.get' => 1,
1515 'api.Membership.getCount' => array(),
1517 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1518 $this->assertEquals(1, $result['id']);
1519 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
1520 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
1521 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
1523 $this->callAPISuccess('contact', 'delete', $result);
1524 $this->customGroupDelete($ids['custom_group_id']);
1525 $this->customGroupDelete($moreids['custom_group_id']);
1528 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
1529 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1530 $params['custom_' . $ids['custom_field_id']] = "custom string";
1531 $moreids = $this->CustomGroupMultipleCreateWithFields();
1532 $andmoreids = $this->CustomGroupMultipleCreateWithFields(array(
1533 'title' => "another group",
1534 'name' => 'another name',
1536 $description = "/*this demonstrates the usage of chained api functions. A variety of techniques are used";
1537 $subfile = "APIChainedArrayMultipleCustom";
1539 'first_name' => 'abc3',
1540 'last_name' => 'xyz3',
1541 'contact_type' => 'Individual',
1542 'email' => 'man3@yahoo.com',
1543 'api.contribution.create' => array(
1544 'receive_date' => '2010-01-01',
1545 'total_amount' => 100.00,
1546 'financial_type_id' => 1,
1547 'payment_instrument_id' => 1,
1548 'non_deductible_amount' => 10.00,
1549 'fee_amount' => 50.00,
1550 'net_amount' => 90.00,
1552 'invoice_id' => 67890,
1554 'contribution_status_id' => 1,
1556 'api.contribution.create.1' => array(
1557 'receive_date' => '2011-01-01',
1558 'total_amount' => 120.00,
1559 'financial_type_id' => 1,
1560 'payment_instrument_id' => 1,
1561 'non_deductible_amount' => 10.00,
1562 'fee_amount' => 50.00,
1563 'net_amount' => 90.00,
1565 'invoice_id' => 67830,
1567 'contribution_status_id' => 1,
1569 'api.website.create' => array(
1571 'url' => "http://civicrm.org",
1574 'custom_' . $ids['custom_field_id'] => "value 1",
1575 'custom_' . $moreids['custom_field_id'][0] => "value 2",
1576 'custom_' . $moreids['custom_field_id'][1] => "warm beer",
1577 'custom_' . $andmoreids['custom_field_id'][1] => "vegemite",
1580 $result = $this->callAPISuccess('Contact', 'create', $params);
1581 $result = $this->callAPISuccess('Contact', 'create', array(
1582 'contact_type' => 'Individual',
1583 'id' => $result['id'],
1585 $moreids['custom_field_id'][0] => "value 3",
1587 $ids['custom_field_id'] => "value 4",
1591 'id' => $result['id'],
1592 'api.website.getValue' => array('return' => 'url'),
1593 'api.Contribution.getCount' => array(),
1594 'api.CustomValue.get' => 1,
1596 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1598 $this->customGroupDelete($ids['custom_group_id']);
1599 $this->customGroupDelete($moreids['custom_group_id']);
1600 $this->customGroupDelete($andmoreids['custom_group_id']);
1601 $this->assertEquals(1, $result['id']);
1602 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
1603 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
1607 * Test checks siusage of $values to pick & choose inputs
1609 public function testChainingValuesCreate() {
1610 $description = "/*this demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
1611 2 child functions - one receives values from the parent (Contact) and the other child (Tag). ";
1612 $subfile = "APIChainedArrayValuesFromSiblingFunction";
1614 'display_name' => 'batman',
1615 'contact_type' => 'Individual',
1616 'api.tag.create' => array('name' => '$value.id', 'description' => '$value.display_name', 'format.only_id' => 1),
1617 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
1619 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1620 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
1622 $tablesToTruncate = array(
1625 'civicrm_entity_tag',
1628 $this->quickCleanup($tablesToTruncate, TRUE);
1632 * test TrueFalse format - I couldn't come up with an easy way to get an error on Get
1634 public function testContactGetFormatIsSuccessTrue() {
1635 $this->createContactFromXML();
1636 $description = "This demonstrates use of the 'format.is_success' param.
1637 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1638 $subfile = "FormatIsSuccess_True";
1639 $params = array('id' => 17, 'format.is_success' => 1);
1640 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1641 $this->assertEquals(1, $result);
1642 $this->callAPISuccess('Contact', 'Delete', $params);
1646 * test TrueFalse format
1648 public function testContactCreateFormatIsSuccessFalse() {
1650 $description = "This demonstrates use of the 'format.is_success' param.
1651 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1652 $subfile = "FormatIsSuccess_Fail";
1653 $params = array('id' => 500, 'format.is_success' => 1);
1654 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1655 $this->assertEquals(0, $result);
1659 * test Single Entity format
1661 public function testContactGetSingle_entity_array() {
1662 $this->createContactFromXML();
1663 $description = "This demonstrates use of the 'format.single_entity_array' param.
1664 /* This param causes the only contact to be returned as an array without the other levels.
1665 /* it will be ignored if there is not exactly 1 result";
1666 $subfile = "GetSingleContact";
1667 $params = array('id' => 17);
1668 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1669 $this->assertEquals('Test Contact', $result['display_name']);
1670 $this->callAPISuccess('Contact', 'Delete', $params);
1674 * test Single Entity format
1676 public function testContactGetFormatcount_only() {
1677 $this->createContactFromXML();
1678 $description = "/*This demonstrates use of the 'getCount' action
1679 /* This param causes the count of the only function to be returned as an integer";
1680 $subfile = "GetCountContact";
1681 $params = array('id' => 17);
1682 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1683 $this->assertEquals('1', $result);
1684 $this->callAPISuccess('Contact', 'Delete', $params);
1688 * Test id only format
1690 public function testContactGetFormatID_only() {
1691 $this->createContactFromXML();
1692 $description = "This demonstrates use of the 'format.id_only' param.
1693 /* This param causes the id of the only entity to be returned as an integer.
1694 /* it will be ignored if there is not exactly 1 result";
1695 $subfile = "FormatOnlyID";
1696 $params = array('id' => 17, 'format.only_id' => 1);
1697 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1698 $this->assertEquals('17', $result);
1699 $this->callAPISuccess('Contact', 'Delete', $params);
1703 * Test id only format
1705 public function testContactGetFormatSingleValue() {
1706 $this->createContactFromXML();
1707 $description = "This demonstrates use of the 'format.single_value' param.
1708 /* This param causes only a single value of the only entity to be returned as an string.
1709 /* it will be ignored if there is not exactly 1 result";
1710 $subFile = "FormatSingleValue";
1711 $params = array('id' => 17, 'return' => 'display_name');
1712 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__
, __FILE__
, $description, $subFile, 'getvalue');
1713 $this->assertEquals('Test Contact', $result);
1714 $this->callAPISuccess('Contact', 'Delete', $params);
1718 * Test that permissions are respected when creating contacts
1720 public function testContactCreationPermissions() {
1722 'contact_type' => 'Individual',
1723 'first_name' => 'Foo',
1724 'last_name' => 'Bear',
1725 'check_permissions' => TRUE,
1727 $config = CRM_Core_Config
::singleton();
1728 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1729 $result = $this->callAPIFailure('contact', 'create', $params);
1730 $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');
1732 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'add contacts', 'import contacts');
1733 $this->callAPISuccess('contact', 'create', $params, NULL, 'overfluous permissions should be enough to create a contact');
1736 public function testContactUpdatePermissions() {
1738 'contact_type' => 'Individual',
1739 'first_name' => 'Foo',
1740 'last_name' => 'Bear',
1741 'check_permissions' => TRUE,
1743 $result = $this->callAPISuccess('contact', 'create', $params);
1744 $config = CRM_Core_Config
::singleton();
1746 'id' => $result['id'],
1747 'contact_type' => 'Individual',
1748 'last_name' => 'Bar',
1749 'check_permissions' => TRUE,
1752 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1753 $result = $this->callAPIFailure('contact', 'update', $params);
1754 $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');
1756 $config->userPermissionClass
->permissions
= array(
1759 'view all contacts',
1760 'edit all contacts',
1763 $this->callAPISuccess('contact', 'update', $params, NULL, 'overfluous permissions should be enough to update a contact');
1766 public function createContactFromXML() {
1767 // Insert a row in civicrm_contact creating contact 17
1768 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1769 $op->execute($this->_dbconn
,
1770 $this->createXMLDataSet(
1771 dirname(__FILE__
) . '/dataset/contact_17.xml'
1776 public function testContactProximity() {
1777 // first create a contact with a SF location with a specific
1779 $contactID = $this->organizationCreate();
1781 // now create the address
1783 'street_address' => '123 Main Street',
1784 'city' => 'San Francisco',
1786 'country_id' => 1228,
1787 'state_province_id' => 1004,
1788 'geo_code_1' => '37.79',
1789 'geo_code_2' => '-122.40',
1790 'location_type_id' => 1,
1791 'contact_id' => $contactID,
1794 $result = $this->callAPISuccess('address', 'create', $params);
1795 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1797 // now do a proximity search with a close enough geocode and hope to match
1798 // that specific contact only!
1799 $proxParams = array(
1801 'longitude' => -122.3,
1805 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
1806 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1810 * Test that Ajax API permission is sufficient to access getquick api
1811 * (note that getquick api is required for autocomplete & has ACL permissions applied)
1813 public function testGetquickPermission_CRM_13744() {
1814 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviEvent');
1815 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1816 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
1817 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1818 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access AJAX API');
1819 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1823 * Test get ref api - gets a list of references to an entity
1825 public function testGetReferenceCounts() {
1826 $result = $this->callAPISuccess('Contact', 'create', array(
1827 'first_name' => 'Testily',
1828 'last_name' => 'McHaste',
1829 'contact_type' => 'Individual',
1830 'api.Address.replace' => array(
1831 'values' => array(),
1833 'api.Email.replace' => array(
1836 'email' => 'spam@dev.null',
1838 'location_type_id' => 1,
1842 'api.Phone.replace' => array(
1845 'phone' => '234-567-0001',
1847 'location_type_id' => 1,
1850 'phone' => '234-567-0002',
1852 'location_type_id' => 1,
1858 //$dao = new CRM_Contact_BAO_Contact();
1859 //$dao->id = $result['id'];
1860 //$this->assertTrue((bool) $dao->find(TRUE));
1862 //$refCounts = $dao->getReferenceCounts();
1863 //$this->assertTrue(is_array($refCounts));
1864 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
1866 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
1867 'id' => $result['id'],
1869 $refCountsIdx = CRM_Utils_Array
::index(array('name'), $refCounts['values']);
1871 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
1872 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
1873 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
1874 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
1875 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
1878 public function testSQLOperatorsOnContactAPI() {
1879 $this->individualCreate();
1880 $this->organizationCreate();
1881 $this->householdCreate();
1882 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
1883 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
1884 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
1885 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
1889 * CRM-14743 - test api respects search operators
1891 public function testGetModifiedDateByOperators() {
1892 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1893 $contact1 = $this->individualCreate();
1894 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
1895 CRM_Core_DAO
::executeQuery($sql);
1896 $contact2 = $this->individualCreate();
1897 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
1898 CRM_Core_DAO
::executeQuery($sql);
1899 $contact3 = $this->householdCreate();
1900 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
1901 CRM_Core_DAO
::executeQuery($sql);
1902 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
1903 $this->assertEquals($contacts['count'], 3);
1904 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
1905 $this->assertEquals($contacts['count'], $preExistingContactCount);
1909 * CRM-14743 - test api respects search operators
1911 public function testGetCreatedDateByOperators() {
1912 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1913 $contact1 = $this->individualCreate();
1914 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
1915 CRM_Core_DAO
::executeQuery($sql);
1916 $contact2 = $this->individualCreate();
1917 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
1918 CRM_Core_DAO
::executeQuery($sql);
1919 $contact3 = $this->householdCreate();
1920 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
1921 CRM_Core_DAO
::executeQuery($sql);
1922 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
1923 $this->assertEquals($contacts['count'], 3);
1924 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
1925 $this->assertEquals($contacts['count'], $preExistingContactCount);
1929 * CRM-14263 check that API is not affected by search profile related bug
1931 public function testReturnCityProfile() {
1932 $contactID = $this->individualCreate();
1933 CRM_Core_Config
::singleton()->defaultSearchProfileID
= 1;
1934 $this->callAPISuccess('address', 'create', array(
1935 'contact_id' => $contactID,
1936 'city' => 'Cool City',
1937 'location_type_id' => 1,
1939 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
1940 $this->assertEquals(1, $result['count']);
1944 * CRM-15443 - ensure getlist api does not return deleted contacts
1946 public function testGetlistExcludeConditions() {
1947 $name = md5(time());
1948 $contact = $this->individualCreate(array('last_name' => $name));
1949 $deceasedContact = $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
1950 $deletedContact = $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
1951 // We should get all but the deleted contact
1952 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
1953 $this->assertEquals(2, $result['count'], 'In line ' . __LINE__
);
1954 // Force-exclude the deceased contact
1955 $result = $this->callAPISuccess('contact', 'getlist', array(
1957 'params' => array('is_deceased' => 0),
1959 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1960 $this->assertEquals($contact, $result['values'][0]['id'], 'In line ' . __LINE__
);
1964 * Test contact.getactions
1966 public function testGetActions() {
1967 $description = "Getting the available actions for an entity.";
1968 $result = $this->callAPIAndDocument($this->_entity
, 'getactions', array(), __FUNCTION__
, __FILE__
, $description);
1988 $deprecated = array(
1992 foreach ($expected as $action) {
1993 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
1995 foreach ($deprecated as $action) {
1996 $this->assertArrayKeyExists($action, $result['deprecated']);