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
44 class api_v3_ContactTest
extends CiviUnitTestCase
{
45 public $DBResetRequired = FALSE;
46 protected $_apiversion;
50 protected $_contactID;
51 protected $_financialTypeId =1;
56 * Initialize configuration
58 function __construct() {
59 parent
::__construct();
63 * Test setup for every test
65 * Connect to the database, truncate the tables that will be used
66 * and redirect stdin to a temporary file
68 public function setUp() {
69 // Connect to the database
71 $this->_apiversion
= 3;
72 $this->_entity
= 'contact';
73 $this->_params
= array(
74 'first_name' => 'abc1',
75 'contact_type' => 'Individual',
76 'last_name' => 'xyz1',
81 // truncate a few tables
82 $tablesToTruncate = array(
85 'civicrm_contribution',
88 'civicrm_relationship',
93 $this->quickCleanup($tablesToTruncate, TRUE);
97 * Test civicrm_contact_create
99 * Verify that attempt to create individual contact with only
100 * first and last names succeeds
102 function testAddCreateIndividual() {
103 $oldCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
105 'first_name' => 'abc1',
106 'contact_type' => 'Individual',
107 'last_name' => 'xyz1',
110 $contact = $this->callAPISuccess('contact', 'create', $params);
111 $this->assertTrue(is_numeric($contact['id']), "In line " . __LINE__
);
112 $this->assertTrue($contact['id'] > 0, "In line " . __LINE__
);
113 $newCount = CRM_Core_DAO
::singleValueQuery('select count(*) from civicrm_contact');
114 $this->assertEquals($oldCount+
1, $newCount);
116 $this->assertDBState('CRM_Contact_DAO_Contact',
123 * Test civicrm_contact_create with sub-types
125 * Verify that sub-types are created successfully and not deleted by subsequent updates
127 function testIndividualSubType() {
129 'first_name' => 'test abc',
130 'contact_type' => 'Individual',
131 'last_name' => 'test xyz',
132 'contact_sub_type' => array('Student', 'Staff'),
134 $contact = $this->callAPISuccess('contact', 'create', $params);
135 $cid = $contact['id'];
139 'middle_name' => 'foo',
141 $this->callAPISuccess('contact', 'create', $params);
142 unset($params['middle_name']);
144 $contact = $this->callAPISuccess('contact', 'get', $params);
146 $this->assertEquals(array('Student', 'Staff'), $contact['values'][$cid]['contact_sub_type'], "In line " . __LINE__
);
150 * Verify that attempt to create contact with empty params fails
152 function testCreateEmptyContact() {
153 $this->callAPIFailure('contact', 'create', array());
157 * Verify that attempt to create contact with bad contact type fails
159 function testCreateBadTypeContact() {
161 'email' => 'man1@yahoo.com',
162 'contact_type' => 'Does not Exist',
164 $this->callAPIFailure('contact', 'create', $params,"'Does not Exist' is not a valid option for field contact_type");
168 * Verify that attempt to create individual contact with required
169 * fields missing fails
171 function testCreateBadRequiredFieldsIndividual() {
173 'middle_name' => 'This field is not required',
174 'contact_type' => 'Individual',
176 $this->callAPIFailure('contact', 'create', $params);
180 * Verify that attempt to create household contact with required
181 * fields missing fails
183 function testCreateBadRequiredFieldsHousehold() {
185 'middle_name' => 'This field is not required',
186 'contact_type' => 'Household',
188 $this->callAPIFailure('contact', 'create', $params);
192 * Verify that attempt to create organization contact with
193 * required fields missing fails
195 function testCreateBadRequiredFieldsOrganization() {
197 'middle_name' => 'This field is not required',
198 'contact_type' => 'Organization',
201 $this->callAPIFailure('contact', 'create', $params);
205 * Verify that attempt to create individual contact with only an
208 function testCreateEmailIndividual() {
211 'email' => 'man3@yahoo.com',
212 'contact_type' => 'Individual',
213 'location_type_id' => 1,
216 $contact = $this->callAPISuccess('contact', 'create', $params);
218 $this->assertEquals(1, $contact['id'], "In line " . __LINE__
);
219 $email = $this->callAPISuccess('email', 'get', array('contact_id' => $contact['id']));
220 $this->assertEquals(1, $email['count']);
221 $this->assertEquals('man3@yahoo.com', $email['values'][$email['id']]['email']);
223 $this->callAPISuccess('contact', 'delete', $contact);
227 * Verify that attempt to create individual contact with only
228 * first and last names succeeds
230 function testCreateNameIndividual() {
232 'first_name' => 'abc1',
233 'contact_type' => 'Individual',
234 'last_name' => 'xyz1',
237 $contact = $this->callAPISuccess('contact', 'create', $params);
238 $this->assertEquals(1, $contact['id']);
242 * Verify that attempt to create individual contact with
243 * first and last names and old key values works
245 function testCreateNameIndividualOldKeys() {
247 'individual_prefix' => 'Dr.',
248 'first_name' => 'abc1',
249 'contact_type' => 'Individual',
250 'last_name' => 'xyz1',
251 'individual_suffix' => 'Jr.',
254 $contact = $this->callAPISuccess('contact', 'create', $params);
255 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
257 $this->assertArrayKeyExists('prefix_id', $result);
258 $this->assertArrayKeyExists('suffix_id', $result);
259 $this->assertArrayKeyExists('gender_id', $result);
260 $this->assertEquals(4, $result['prefix_id']);
261 $this->assertEquals(1, $result['suffix_id']);
265 * Verify that attempt to create individual contact with
266 * first and last names and old key values works
268 function testCreateNameIndividualrecommendedKeys2() {
270 'prefix_id' => 'Dr.',
271 'first_name' => 'abc1',
272 'contact_type' => 'Individual',
273 'last_name' => 'xyz1',
274 'suffix_id' => 'Jr.',
275 'gender_id' => 'Male',
278 $contact = $this->callAPISuccess('contact', 'create', $params);
279 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
281 $this->assertArrayKeyExists('prefix_id', $result);
282 $this->assertArrayKeyExists('suffix_id', $result);
283 $this->assertArrayKeyExists('gender_id', $result);
284 $this->assertEquals(4, $result['prefix_id']);
285 $this->assertEquals(1, $result['suffix_id']);
289 * Verify that attempt to create household contact with only
290 * household name succeeds
292 function testCreateNameHousehold() {
294 'household_name' => 'The abc Household',
295 'contact_type' => 'Household',
297 $contact = $this->callAPISuccess('contact', 'create', $params);
298 $this->assertEquals(1, $contact['id'], "In line " . __LINE__
);
302 * Verify that attempt to create organization contact with only
303 * organization name succeeds
305 function testCreateNameOrganization() {
307 'organization_name' => 'The abc Organization',
308 'contact_type' => 'Organization',
310 $contact = $this->callAPISuccess('contact', 'create', $params);
311 $this->assertEquals(1, $contact['id']);
314 * Verify that attempt to create organization contact without organization name fails
316 function testCreateNoNameOrganization() {
318 'first_name' => 'The abc Organization',
319 'contact_type' => 'Organization',
321 $this->callAPIFailure('contact', 'create', $params);
324 * check with complete array + custom field
325 * Note that the test is written on purpose without any
326 * variables specific to participant so it can be replicated into other entities
327 * and / or moved to the automated test suite
329 function testCreateWithCustom() {
330 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
332 $params = $this->_params
;
333 $params['custom_' . $ids['custom_field_id']] = "custom string";
334 $description = "/*this demonstrates setting a custom field through the API ";
335 $result = $this->callAPIAndDocument($this->_entity
, 'create', $params, __FUNCTION__
, __FILE__
, $description);
337 $check = $this->callAPISuccess($this->_entity
, 'get', array('return.custom_' . $ids['custom_field_id'] => 1, 'id' => $result['id']));
338 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
340 $this->customFieldDelete($ids['custom_field_id']);
341 $this->customGroupDelete($ids['custom_group_id']);
345 * CRM-12773 - expectation is that civicrm quietly ignores
346 * fields without values
348 function testCreateWithNULLCustomCRM12773() {
349 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
350 $params = $this->_params
;
351 $params['custom_' . $ids['custom_field_id']] = NULL;
352 $this->callAPISuccess('contact', 'create', $params);
353 $this->customFieldDelete($ids['custom_field_id']);
354 $this->customGroupDelete($ids['custom_group_id']);
359 * Test creating a current employer through API
361 function testContactCreateCurrentEmployer(){
362 //here we will just do the get for set-up purposes
363 $count = $this->callAPISuccess('contact', 'getcount', array(
364 'organization_name' => 'new employer org',
365 'contact_type' => 'Organization'
367 $this->assertEquals(0, $count);
368 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
369 'current_employer' => 'new employer org',)
371 // do it again as an update to check it doesn't cause an error
372 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
373 'current_employer' => 'new employer org', 'id' => $employerResult['id'])
376 $this->callAPISuccess('contact', 'getcount', array(
377 'organization_name' => 'new employer org',
378 'contact_type' => 'Organization'
382 $result = $this->callAPISuccess('contact', 'getsingle', array(
383 'id' => $employerResult['id'],
386 $this->assertEquals('new employer org', $result['current_employer']);
390 * Test creating a current employer through API
391 * - check it will re-activate a de-activated employer
393 function testContactCreateDuplicateCurrentEmployerEnables(){
394 //set up - create employer relationship
395 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array(
396 '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', 'id' => $employerResult['id'])
413 //check is_active is now 1
414 $relationship = $this->callAPISuccess('relationship','getsingle', array(
415 'return' => 'is_active',));
416 $this->assertEquals(1, $relationship['is_active']);
420 * Check deceased contacts are not retrieved
421 * Note at time of writing the default is to return default. This should possibly be changed & test added
423 function testGetDeceasedRetrieved() {
424 $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
425 $c2 = $this->callAPISuccess($this->_entity
, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual', 'is_deceased' => 1));
426 $result = $this->callAPISuccess($this->_entity
, 'get', array('is_deceased' => 0));
427 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
431 * Test that sort works - old syntax
433 function testGetSort() {
434 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
435 $c2 = $this->callAPISuccess($this->_entity
, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual'));
436 $result = $this->callAPISuccess($this->_entity
, 'get', array(
437 'sort' => 'first_name ASC',
438 'return.first_name' => 1,
443 $this->assertEquals('abc1', $result['values'][0]['first_name']);
444 $result = $this->callAPISuccess($this->_entity
, 'get', array(
445 'sort' => 'first_name DESC',
446 'return.first_name' => 1,
450 $this->assertEquals('bb', $result['values'][0]['first_name']);
452 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
453 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
456 * Test that we can retrieve contacts using
457 * 'id' => array('IN' => array('3,4')) syntax
459 function testGetINIDArray() {
460 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
461 $c2 = $this->callAPISuccess($this->_entity
, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual'));
462 $c3 = $this->callAPISuccess($this->_entity
, 'create', array('first_name' => 'hh', 'last_name' => 'll', 'contact_type' => 'Individual'));
463 $result = $this->callAPISuccess($this->_entity
, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
464 $this->assertEquals(2, $result['count']);
465 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
466 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
467 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
468 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c3['id']));
471 * Test variants on deleted behaviour
473 function testGetDeleted() {
474 $params = $this->_params
;
475 $contact1 = $this->callAPISuccess('contact', 'create', $params);
476 $params['is_deleted'] = 1;
477 $params['last_name'] = 'bcd';
478 $contact2 = $this->callAPISuccess('contact', 'create', $params);
479 $countActive = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'active'));
480 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all'));
481 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash'));
482 $countDefault = $this->callAPISuccess('contact', 'getcount', array());
483 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
484 'contact_is_deleted' => 1,
486 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
487 'contact_is_deleted' => 0,
489 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
490 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
491 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected in line ' . __LINE__
);
492 $this->assertEquals(1, $countActive, 'in line ' . __LINE__
);
493 $this->assertEquals(1, $countTrash, 'in line ' . __LINE__
);
494 $this->assertEquals(2, $countAll, 'in line ' . __LINE__
);
495 $this->assertEquals(1, $countDeleted, 'in line ' . __LINE__
);
496 $this->assertEquals(1, $countDefault, 'Only active by default in line ' . __LINE__
);
500 * Test that sort works - new syntax
502 function testGetSortNewSYntax() {
503 $c1 = $this->callAPISuccess($this->_entity
, 'create', $this->_params
);
504 $c2 = $this->callAPISuccess($this->_entity
, 'create', array('first_name' => 'bb', 'last_name' => 'ccc', 'contact_type' => 'Individual'));
505 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
506 'return' => 'first_name',
509 'sort' => 'first_name',
512 $this->assertEquals('abc1', $result, 'in line' . __LINE__
);
514 $result = $this->callAPISuccess($this->_entity
, 'getvalue', array(
515 'return' => 'first_name',
518 'sort' => 'first_name DESC',
521 $this->assertEquals('bb', $result);
523 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c1['id']));
524 $this->callAPISuccess($this->_entity
, 'delete', array('id' => $c2['id']));
528 * Test apostrophe works in get & create
530 function testGetApostropheCRM10857() {
531 $params = array_merge($this->_params
, array('last_name' => "O'Connor"));
532 $this->callAPISuccess($this->_entity
, 'create', $params);
533 $result = $this->callAPISuccess($this->_entity
, 'getsingle', array(
534 'last_name' => "O'Connor",
537 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__
);
541 * check with complete array + custom field
542 * Note that the test is written on purpose without any
543 * variables specific to participant so it can be replicated into other entities
544 * and / or moved to the automated test suite
546 function testGetWithCustom() {
547 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
549 $params = $this->_params
;
550 $params['custom_' . $ids['custom_field_id']] = "custom string";
551 $description = "/*this demonstrates setting a custom field through the API ";
552 $subfile = "CustomFieldGet";
553 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
555 $check = $this->callAPIAndDocument($this->_entity
, 'get', array('return.custom_' . $ids['custom_field_id'] => 1, 'id' => $result['id']), __FUNCTION__
, __FILE__
, $description, $subfile);
557 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
558 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
559 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
560 $this->customFieldDelete($ids['custom_field_id']);
561 $this->customGroupDelete($ids['custom_group_id']);
565 * check with complete array + custom field
566 * Note that the test is written on purpose without any
567 * variables specific to participant so it can be replicated into other entities
568 * and / or moved to the automated test suite
570 function testGetWithCustomReturnSyntax() {
571 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
573 $params = $this->_params
;
574 $params['custom_' . $ids['custom_field_id']] = "custom string";
575 $description = "/*this demonstrates setting a custom field through the API ";
576 $subfile = "CustomFieldGetReturnSyntaxVariation";
577 $result = $this->callAPISuccess($this->_entity
, 'create', $params);
578 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
579 $check = $this->callAPIAndDocument($this->_entity
, 'get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
581 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
582 $this->customFieldDelete($ids['custom_field_id']);
583 $this->customGroupDelete($ids['custom_group_id']);
587 * Check that address name is returned if required
589 function testGetReturnAddressName () {
590 $contactID = $this->individualCreate();
591 $this->callAPISuccess('address', 'create', array('contact_id' => $contactID, 'address_name' => 'My house', 'location_type_id' => 'Home', 'street_address' => '1 my road'));
592 $result = $this->callAPISuccessGetSingle('contact', array('return' => 'address_name, street_address', 'id' => $contactID));
593 $this->assertEquals('1 my road', $result['street_address']);
594 $this->assertEquals('My house', $result['address_name']);
598 function testGetGroupIDFromContact() {
599 $groupId = $this->groupCreate();
600 $description = "Get all from group and display contacts";
601 $subFile = "GroupFilterUsingContactAPI";
603 'email' => 'man2@yahoo.com',
604 'contact_type' => 'Individual',
605 'location_type_id' => 1,
606 'api.group_contact.create' => array('group_id' => $groupId),
609 $this->callAPISuccess('contact', 'create', $params);
610 // testing as integer
612 'filter.group_id' => $groupId,
613 'contact_type' => 'Individual',
615 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
616 $this->assertEquals(1, $result['count']);
617 // group 26 doesn't exist, but we can still search contacts in it.
619 'filter.group_id' => 26,
620 'contact_type' => 'Individual',
622 $this->callAPISuccess('contact', 'get', $params);
625 'filter.group_id' => "$groupId, 26",
626 'contact_type' => 'Individual',
628 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
629 $this->assertEquals(1, $result['count']);
631 'filter.group_id' => "26,27",
632 'contact_type' => 'Individual',
634 $this->callAPISuccess('contact', 'get', $params);
637 $params = array('filter.group_id' => array($groupId, 26),
638 'contact_type' => 'Individual',
640 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
641 $this->assertEquals(1, $result['count']);
643 //test in conjunction with other criteria
644 $params = array('filter.group_id' => array($groupId, 26),
645 'contact_type' => 'Organization',
647 $this->callAPISuccess('contact', 'get', $params);
648 $params = array('filter.group_id' => array(26, 27),
649 'contact_type' => 'Individual',
651 $result = $this->callAPISuccess('contact', 'get', $params);
652 $this->assertEquals(0, $result['count']);
656 * Verify that attempt to create individual contact with two chained websites succeeds
658 function testCreateIndividualWithContributionDottedSyntax() {
659 $description = "test demonstrates the syntax to create 2 chained entities";
660 $subFile = "ChainTwoWebsites";
662 'first_name' => 'abc3',
663 'last_name' => 'xyz3',
664 'contact_type' => 'Individual',
665 'email' => 'man3@yahoo.com',
666 'api.contribution.create' => array(
667 'receive_date' => '2010-01-01',
668 'total_amount' => 100.00,
669 'financial_type_id' => $this->_financialTypeId
,
670 'payment_instrument_id' => 1,
671 'non_deductible_amount' => 10.00,
672 'fee_amount' => 50.00,
673 'net_amount' => 90.00,
675 'invoice_id' => 67990,
677 'contribution_status_id' => 1,
679 'api.website.create' => array(
680 'url' => "http://civicrm.org",
682 'api.website.create.2' => array(
683 'url' => "http://chained.org",
687 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subFile);
689 $this->assertEquals(1, $result['id'], "In line " . __LINE__
);
690 // checking child function result not covered in callAPIAndDocument
691 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
692 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url'], "In line " . __LINE__
);
693 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url'], "In line " . __LINE__
);
695 // delete the contact
696 $this->callAPISuccess('contact', 'delete', $result);
700 * Verify that attempt to create individual contact with chained contribution and website succeeds
702 function testCreateIndividualWithContributionChainedArrays() {
704 'first_name' => 'abc3',
705 'last_name' => 'xyz3',
706 'contact_type' => 'Individual',
707 'email' => 'man3@yahoo.com',
708 'api.contribution.create' => array(
709 'receive_date' => '2010-01-01',
710 'total_amount' => 100.00,
711 'financial_type_id' => $this->_financialTypeId
,
712 'payment_instrument_id' => 1,
713 'non_deductible_amount' => 10.00,
714 'fee_amount' => 50.00,
715 'net_amount' => 90.00,
717 'invoice_id' => 67890,
719 'contribution_status_id' => 1,
721 'api.website.create' => array(
723 'url' => "http://civicrm.org",
726 'url' => "http://chained.org",
727 'website_type_id' => 2,
732 $description = "demonstrates creating two websites as an array";
733 $subfile = "ChainTwoWebsitesSyntax2";
734 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
736 $this->assertEquals(1, $result['id']);
737 // the callAndDocument doesn't check the chained call
738 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error'], "In line " . __LINE__
);
739 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url'], "In line " . __LINE__
);
740 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url'], "In line " . __LINE__
);
742 $this->callAPISuccess('contact', 'delete', $result);
746 * Verify that attempt to create individual contact with first
747 * and last names and email succeeds
749 function testCreateIndividualWithNameEmail() {
751 'first_name' => 'abc3',
752 'last_name' => 'xyz3',
753 'contact_type' => 'Individual',
754 'email' => 'man3@yahoo.com',
757 $contact = $this->callAPISuccess('contact', 'create', $params);
758 $this->assertEquals(1, $contact['id'], "In line " . __LINE__
);
760 // delete the contact
761 $this->callAPISuccess('contact', 'delete', $contact);
764 * Verify that attempt to create individual contact with no data fails
766 function testCreateIndividualWithOutNameEmail() {
768 'contact_type' => 'Individual',
770 $this->callAPIFailure('contact', 'create', $params);
773 * Verify that attempt to create individual contact with first
774 * and last names, email and location type succeeds
776 function testCreateIndividualWithNameEmailLocationType() {
778 'first_name' => 'abc4',
779 'last_name' => 'xyz4',
780 'email' => 'man4@yahoo.com',
781 'contact_type' => 'Individual',
782 'location_type_id' => 1,
784 $result = $this->callAPISuccess('contact', 'create', $params);
786 $this->assertEquals(1, $result['id'], "In line " . __LINE__
);
788 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
792 * Verify that when changing employers
793 * the old employer relationship becomes inactive
795 function testCreateIndividualWithEmployer() {
796 $employer = $this->organizationCreate();
797 $employer2 = $this->organizationCreate();
800 'email' => 'man4@yahoo.com',
801 'contact_type' => 'Individual',
802 'employer_id' => $employer,
805 $result = $this->callAPISuccess('contact', 'create', $params);
806 $relationships = $this->callAPISuccess('relationship', 'get', array(
807 'contact_id_a' => $result['id'],
811 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
813 // Add more random relationships to make the test more realistic
814 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
815 $relTypeId = CRM_Core_DAO
::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
816 $this->callAPISuccess('relationship', 'create', array(
817 'contact_id_a' => $result['id'],
818 'contact_id_b' => $this->organizationCreate(),
820 'relationship_type_id' => $relTypeId,
824 // Add second employer
825 $params['employer_id'] = $employer2;
826 $params['id'] = $result['id'];
827 $result = $this->callAPISuccess('contact', 'create', $params);
829 $relationships = $this->callAPISuccess('relationship', 'get', array(
830 'contact_id_a' => $result['id'],
835 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
839 * Verify that attempt to create household contact with details
842 function testCreateHouseholdDetails() {
844 'household_name' => 'abc8\'s House',
845 'nick_name' => 'x House',
846 'email' => 'man8@yahoo.com',
847 'contact_type' => 'Household',
850 $contact = $this->callAPISuccess('contact', 'create', $params);
852 $this->assertEquals(1, $contact['id'], "In line " . __LINE__
);
854 $this->callAPISuccess('contact', 'delete', $contact);
857 * Verify that attempt to create household contact with inadequate details
860 function testCreateHouseholdInadequateDetails() {
862 'nick_name' => 'x House',
863 'email' => 'man8@yahoo.com',
864 'contact_type' => 'Household',
866 $this->callAPIFailure('contact', 'create', $params);
870 * Verify successful update of individual contact
872 function testUpdateIndividualWithAll() {
873 // Insert a row in civicrm_contact creating individual contact
874 $op = new PHPUnit_Extensions_Database_Operation_Insert();
875 $op->execute($this->_dbconn
,
876 $this->createXMLDataSet(
877 dirname(__FILE__
) . '/dataset/contact_ind.xml'
883 'first_name' => 'abcd',
884 'contact_type' => 'Individual',
885 'nick_name' => 'This is nickname first',
886 'do_not_email' => '1',
887 'do_not_phone' => '1',
888 'do_not_mail' => '1',
889 'do_not_trade' => '1',
890 'legal_identifier' => 'ABC23853ZZ2235',
891 'external_identifier' => '1928837465',
892 'image_URL' => 'http://some.url.com/image.jpg',
893 'home_url' => 'http://www.example.org',
897 $this->callAPISuccess('Contact', 'Update', $params);
898 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
899 unset($params['contact_id']);
900 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
901 //reducing this test partially back to api v2 level to get it through
902 unset($params['home_url']);
903 foreach ($params as $key => $value) {
904 $this->assertEquals($value, $getResult['values'][23][$key]);
906 // Check updated civicrm_contact against expected
907 $expected = $this->createXMLDataSet(
908 dirname(__FILE__
) . '/dataset/contact_ind_upd.xml'
910 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
913 $actual->addTable('civicrm_contact');
914 $expected->matches($actual);
918 * Verify successful update of organization contact
920 function testUpdateOrganizationWithAll() {
921 // Insert a row in civicrm_contact creating organization contact
922 $op = new PHPUnit_Extensions_Database_Operation_Insert();
923 $op->execute($this->_dbconn
,
924 $this->createXMLDataSet(
925 dirname(__FILE__
) . '/dataset/contact_org.xml'
931 'organization_name' => 'WebAccess India Pvt Ltd',
932 'legal_name' => 'WebAccess',
933 'sic_code' => 'ABC12DEF',
934 'contact_type' => 'Organization',
937 $this->callAPISuccess('Contact', 'Update', $params);
939 // Check updated civicrm_contact against expected
940 $expected = $this->createXMLDataSet(
941 dirname(__FILE__
) . '/dataset/contact_org_upd.xml'
943 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
946 $actual->addTable('civicrm_contact');
947 $expected->matches($actual);
951 * Verify successful update of household contact
953 function testUpdateHouseholdwithAll() {
954 // Insert a row in civicrm_contact creating household contact
955 $op = new PHPUnit_Extensions_Database_Operation_Insert();
956 $op->execute($this->_dbconn
,
957 $this->createXMLDataSet(
958 dirname(__FILE__
) . '/dataset/contact_hld.xml'
964 'household_name' => 'ABC household',
965 'nick_name' => 'ABC House',
966 'contact_type' => 'Household',
969 $result = $this->callAPISuccess('Contact', 'Update', $params);
972 'contact_type' => 'Household',
974 'sort_name' => 'ABC household',
975 'display_name' => 'ABC household',
976 'nick_name' => 'ABC House',
978 $this->getAndCheck($expected, $result['id'], 'contact');
982 * Test civicrm_update() Deliberately exclude contact_type as it should still
983 * cope using civicrm_api CRM-7645
986 public function testUpdateCreateWithID() {
987 // Insert a row in civicrm_contact creating individual contact
988 $op = new PHPUnit_Extensions_Database_Operation_Insert();
989 $op->execute($this->_dbconn
,
990 $this->createXMLDataSet(
991 dirname(__FILE__
) . '/dataset/contact_ind.xml'
999 'first_name' => 'abcd',
1000 'last_name' => 'wxyz',
1002 $this->callAPISuccess('Contact', 'Update', $params);
1006 * Test civicrm_contact_delete() with no contact ID
1008 function testContactDeleteNoID() {
1012 $this->callAPIFailure('contact', 'delete', $params);
1016 * Test civicrm_contact_delete() with error
1018 function testContactDeleteError() {
1019 $params = array('contact_id' => 999);
1020 $this->callAPIFailure('contact', 'delete', $params);
1024 * Test civicrm_contact_delete()
1026 function testContactDelete() {
1027 $contactID = $this->individualCreate();
1029 'id' => $contactID ,
1031 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__
, __FILE__
);
1035 * Test civicrm_contact_get() return only first name
1037 public function testContactGetRetFirst() {
1038 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1040 'contact_id' => $contact['id'],
1041 'return_first_name' => TRUE,
1042 'sort' => 'first_name',
1044 $result = $this->callAPISuccess('contact', 'get', $params);
1045 $this->assertEquals(1, $result['count']);
1046 $this->assertEquals($contact['id'], $result['id']);
1047 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1051 * Test civicrm_contact_get() return only first name & last name
1052 * Use comma separated string return with a space
1054 public function testContactGetRetFirstLast() {
1055 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1057 'contact_id' => $contact['id'],
1058 'return' => 'first_name, last_name',
1060 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1061 $this->assertEquals('abc1', $result['first_name']);
1062 $this->assertEquals('xyz1', $result['last_name']);
1063 //check that other defaults not returns
1064 $this->assertArrayNotHasKey('sort_name', $result);
1066 'contact_id' => $contact['id'],
1067 'return' => 'first_name,last_name',
1069 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1070 $this->assertEquals('abc1', $result['first_name']);
1071 $this->assertEquals('xyz1', $result['last_name']);
1072 //check that other defaults not returns
1073 $this->assertArrayNotHasKey('sort_name', $result);
1077 * Test civicrm_contact_get() return only first name & last name
1078 * Use comma separated string return without a space
1080 public function testContactGetRetFirstLastNoComma() {
1081 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1083 'contact_id' => $contact['id'],
1084 'return' => 'first_name,last_name',
1086 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1087 $this->assertEquals('abc1', $result['first_name']);
1088 $this->assertEquals('xyz1', $result['last_name']);
1089 //check that other defaults not returns
1090 $this->assertArrayNotHasKey('sort_name', $result);
1094 * Test civicrm_contact_get() with default return properties
1096 public function testContactGetRetDefault() {
1097 $contactID = $this->individualCreate();
1099 'contact_id' => $contactID,
1100 'sort' => 'first_name',
1102 $result = $this->callAPISuccess('contact', 'get', $params);
1103 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1104 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1108 * Test civicrm_contact_getquick() with empty name param
1110 public function testContactGetQuick() {
1111 // Insert a row in civicrm_contact creating individual contact
1112 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1113 $op->execute($this->_dbconn
,
1114 $this->createXMLDataSet(
1115 dirname(__FILE__
) . '/dataset/contact_17.xml'
1118 $op->execute($this->_dbconn
,
1119 $this->createXMLDataSet(
1120 dirname(__FILE__
) . '/dataset/email_contact_17.xml'
1127 $result = $this->callAPISuccess('contact', 'getquick', $params);
1128 $this->assertEquals(17, $result['values'][0]['id'], 'in line ' . __LINE__
);
1132 * Test civicrm_contact_get) with empty params
1134 public function testContactGetEmptyParams() {
1135 $this->callAPISuccess('contact', 'get', array());
1139 * Test civicrm_contact_get(,true) with no matches
1141 public function testContactGetOldParamsNoMatches() {
1142 // Insert a row in civicrm_contact creating contact 17
1143 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1144 $op->execute($this->_dbconn
,
1145 $this->createXMLDataSet(
1146 dirname(__FILE__
) . '/dataset/contact_17.xml'
1151 'first_name' => 'Fred',
1153 $result = $this->callAPISuccess('contact', 'get', $params);
1154 $this->assertEquals(0, $result['count'], 'in line ' . __LINE__
);
1158 * Test civicrm_contact_get(,true) with one match
1160 public function testContactGetOldParamsOneMatch() {
1161 // Insert a row in civicrm_contact creating contact 17
1162 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1163 $op->execute($this->_dbconn
,
1164 $this->createXMLDataSet(dirname(__FILE__
) . '/dataset/contact_17.xml'
1169 'first_name' => 'Test',
1171 $result = $this->callAPISuccess('contact', 'get', $params);
1172 $this->assertEquals(17, $result['values'][17]['contact_id'], 'in line ' . __LINE__
);
1173 $this->assertEquals(17, $result['id'], 'in line ' . __LINE__
);
1177 * Test civicrm_contact_search_count()
1179 public function testContactGetEmail() {
1181 'email' => 'man2@yahoo.com',
1182 'contact_type' => 'Individual',
1183 'location_type_id' => 1,
1186 $contact = $this->callAPISuccess('contact', 'create', $params);
1188 $this->assertEquals(1, $contact['id']);
1191 'email' => 'man2@yahoo.com',
1193 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
);
1194 $this->assertEquals(1, $result['values'][1]['contact_id']);
1195 $this->assertEquals('man2@yahoo.com', $result['values'][1]['email']);
1197 // delete the contact
1198 $this->callAPISuccess('contact', 'delete', $contact);
1202 * Test birth date params incl value, array & birth_date_high, birth_date_low
1205 public function testContactGetBirthDate() {
1206 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 2 years')));
1207 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 5 years')));
1208 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month -20 years')));
1210 $result = $this->callAPISuccess('contact', 'get', array());
1211 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1212 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1213 $this->assertEquals(1, $result['count']);
1214 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1215 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1216 $this->assertEquals(1, $result['count']);
1217 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1218 $result = $this->callAPISuccess('contact', 'get', array('birth_date_low' => date('Y-m-d', strtotime('-6 years')), 'birth_date_high' => date('Y-m-d', strtotime('- 3 years'))));
1219 $this->assertEquals(1, $result['count']);
1220 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1221 $result = $this->callAPISuccess('contact', 'get', array('birth_date_low' => '-6 years', 'birth_date_high' => '- 3 years'));
1222 $this->assertEquals(1, $result['count']);
1223 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1227 * Test Deceaseddate params incl value, array & Deceased_date_high, Deceaseddate_low
1230 public function testContactGetDeceasedDate() {
1231 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 2 years')));
1232 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 5 years')));
1233 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month -20 years')));
1235 $result = $this->callAPISuccess('contact', 'get', array());
1236 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
1237 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
1238 $this->assertEquals(1, $result['count']);
1239 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1240 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
1241 $this->assertEquals(1, $result['count']);
1242 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
1243 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_low' => '-6 years', 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years'))));
1244 $this->assertEquals(1, $result['count']);
1245 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1249 * Test for Contact.get id=@user:username
1251 function testContactGetByUsername() {
1252 // setup - create contact with a uf-match
1253 $cid = $this->individualCreate(array(
1254 'contact_type' => 'Individual',
1255 'first_name' => 'testGetByUsername',
1256 'last_name' => 'testGetByUsername',
1259 $ufMatchParams = array(
1260 'domain_id' => CRM_Core_Config
::domainID(),
1262 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
1263 'contact_id' => $cid,
1265 $ufMatch = CRM_Core_BAO_UFMatch
::create($ufMatchParams);
1266 $this->assertTrue(is_numeric($ufMatch->id
));
1268 // setup - mock the calls to CRM_Utils_System_*::getUfId
1269 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1270 $userSystem->expects($this->once())
1272 ->with($this->equalTo('exampleUser'))
1273 ->will($this->returnValue(99));
1274 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1277 $result = $this->callAPISuccess('Contact', 'get', array(
1278 'id' => '@user:exampleUser',
1280 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
1284 * Test to check return works OK
1286 function testContactGetReturnValues() {
1287 $extraParams = array('nick_name' => 'Bob', 'phone' => '456', 'email' => 'e@mail.com');
1288 $contactID = $this->individualCreate($extraParams);
1289 //actually it turns out the above doesn't create a phone
1290 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456',));
1291 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
1292 foreach ($extraParams as $key => $value) {
1293 $this->assertEquals($result[$key], $value);
1295 //now we check they are still returned with 'return' key
1296 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID, 'return' => array_keys($extraParams)));
1297 foreach ($extraParams as $key => $value) {
1298 $this->assertEquals($result[$key], $value);
1302 function testCRM13252MultipleChainedPhones() {
1303 $contactID = $this->householdCreate();
1304 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
1306 'contact_id' => $contactID,
1307 'household_name' => 'Household 1',
1308 'contact_type' => 'Household',
1309 'api.phone.create' => array(
1311 'phone' => '111-111-1111',
1312 'location_type_id' => 1,
1313 'phone_type_id' => 1,
1316 'phone' => '222-222-2222',
1317 'location_type_id' => 1,
1318 'phone_type_id' => 2,
1322 $this->callAPISuccess('contact', 'create', $params);
1323 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
1327 * Test for Contact.get id=@user:username (with an invalid username)
1329 function testContactGetByUnknownUsername() {
1330 // setup - mock the calls to CRM_Utils_System_*::getUfId
1331 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1332 $userSystem->expects($this->once())
1334 ->with($this->equalTo('exampleUser'))
1335 ->will($this->returnValue(NULL));
1336 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1339 $result = $this->callAPIFailure('Contact', 'get', array(
1340 'id' => '@user:exampleUser',
1342 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
1346 * Verify attempt to create individual with chained arrays
1348 function testGetIndividualWithChainedArrays() {
1349 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1350 $params['custom_' . $ids['custom_field_id']] = "custom string";
1352 $moreids = $this->CustomGroupMultipleCreateWithFields();
1353 $description = "/*this demonstrates the usage of chained api functions. In this case no notes or custom fields have been created ";
1354 $subfile = "APIChainedArray";
1356 'first_name' => 'abc3',
1357 'last_name' => 'xyz3',
1358 'contact_type' => 'Individual',
1359 'email' => 'man3@yahoo.com',
1360 'api.contribution.create' => array(
1361 'receive_date' => '2010-01-01',
1362 'total_amount' => 100.00,
1363 'financial_type_id' => 1,
1364 'payment_instrument_id' => 1,
1365 'non_deductible_amount' => 10.00,
1366 'fee_amount' => 50.00,
1367 'net_amount' => 90.00,
1369 'invoice_id' => 67890,
1371 'contribution_status_id' => 1,
1373 'api.contribution.create.1' => array(
1374 'receive_date' => '2011-01-01',
1375 'total_amount' => 120.00,
1376 'financial_type_id' => $this->_financialTypeId
=1,
1377 'payment_instrument_id' => 1,
1378 'non_deductible_amount' => 10.00,
1379 'fee_amount' => 50.00,
1380 'net_amount' => 90.00,
1382 'invoice_id' => 67830,
1384 'contribution_status_id' => 1,
1386 'api.website.create' => array(
1388 'url' => "http://civicrm.org",
1393 $result = $this->callAPISuccess('Contact', 'create', $params);
1395 'id' => $result['id'],
1396 'api.website.get' => array(),
1397 'api.Contribution.get' => array(
1398 'total_amount' => '120.00',
1399 ), 'api.CustomValue.get' => 1,
1400 'api.Note.get' => 1,
1402 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1403 // delete the contact
1404 $this->callAPISuccess('contact', 'delete', $result);
1405 $this->customGroupDelete($ids['custom_group_id']);
1406 $this->customGroupDelete($moreids['custom_group_id']);
1407 $this->assertEquals(1, $result['id']);
1408 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
1409 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
1412 function testGetIndividualWithChainedArraysFormats() {
1413 $description = "/*this demonstrates the usage of chained api functions. A variety of return formats are used. Note that no notes
1414 *custom fields or memberships exist";
1415 $subfile = "APIChainedArrayFormats";
1416 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1417 $params['custom_' . $ids['custom_field_id']] = "custom string";
1419 $moreids = $this->CustomGroupMultipleCreateWithFields();
1421 'first_name' => 'abc3',
1422 'last_name' => 'xyz3',
1423 'contact_type' => 'Individual',
1424 'email' => 'man3@yahoo.com',
1425 'api.contribution.create' => array(
1426 'receive_date' => '2010-01-01',
1427 'total_amount' => 100.00,
1428 'financial_type_id' => $this->_financialTypeId
,
1429 'payment_instrument_id' => 1,
1430 'non_deductible_amount' => 10.00,
1431 'fee_amount' => 50.00,
1432 'net_amount' => 90.00,
1434 'contribution_status_id' => 1,
1436 'api.contribution.create.1' => array(
1437 'receive_date' => '2011-01-01',
1438 'total_amount' => 120.00,
1439 'financial_type_id' => $this->_financialTypeId
,
1440 'payment_instrument_id' => 1,
1441 'non_deductible_amount' => 10.00,
1442 'fee_amount' => 50.00,
1443 'net_amount' => 90.00,
1445 'contribution_status_id' => 1,
1447 'api.website.create' => array(
1449 'url' => "http://civicrm.org",
1455 $result = $this->callAPISuccess('Contact', 'create', $params);
1457 'id' => $result['id'],
1458 'api.website.getValue' => array('return' => 'url'),
1459 'api.Contribution.getCount' => array(),
1460 'api.CustomValue.get' => 1,
1461 'api.Note.get' => 1,
1462 'api.Membership.getCount' => array(),
1464 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1465 $this->assertEquals(1, $result['id']);
1466 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
1467 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
1468 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
1470 $this->callAPISuccess('contact', 'delete', $result);
1471 $this->customGroupDelete($ids['custom_group_id']);
1472 $this->customGroupDelete($moreids['custom_group_id']);
1475 function testGetIndividualWithChainedArraysAndMultipleCustom() {
1476 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1477 $params['custom_' . $ids['custom_field_id']] = "custom string";
1478 $moreids = $this->CustomGroupMultipleCreateWithFields();
1479 $andmoreids = $this->CustomGroupMultipleCreateWithFields(array('title' => "another group", 'name' => 'another name'));
1480 $description = "/*this demonstrates the usage of chained api functions. A variety of techniques are used";
1481 $subfile = "APIChainedArrayMultipleCustom";
1483 'first_name' => 'abc3',
1484 'last_name' => 'xyz3',
1485 'contact_type' => 'Individual',
1486 'email' => 'man3@yahoo.com',
1487 'api.contribution.create' => array(
1488 'receive_date' => '2010-01-01',
1489 'total_amount' => 100.00,
1490 'financial_type_id' => 1,
1491 'payment_instrument_id' => 1,
1492 'non_deductible_amount' => 10.00,
1493 'fee_amount' => 50.00,
1494 'net_amount' => 90.00,
1496 'invoice_id' => 67890,
1498 'contribution_status_id' => 1,
1500 'api.contribution.create.1' => array(
1501 'receive_date' => '2011-01-01',
1502 'total_amount' => 120.00,
1503 'financial_type_id' => 1,
1504 'payment_instrument_id' => 1,
1505 'non_deductible_amount' => 10.00,
1506 'fee_amount' => 50.00,
1507 'net_amount' => 90.00,
1509 'invoice_id' => 67830,
1511 'contribution_status_id' => 1,
1513 'api.website.create' => array(
1515 'url' => "http://civicrm.org",
1518 'custom_' . $ids['custom_field_id'] => "value 1",
1519 'custom_' . $moreids['custom_field_id'][0] => "value 2",
1520 'custom_' . $moreids['custom_field_id'][1] => "warm beer",
1521 'custom_' . $andmoreids['custom_field_id'][1] => "vegemite",
1525 $result = $this->callAPISuccess('Contact', 'create', $params);
1526 $result = $this->callAPISuccess('Contact', 'create', array(
1527 'contact_type' => 'Individual', 'id' => $result['id'], 'custom_' . $moreids['custom_field_id'][0] => "value 3", 'custom_' . $ids['custom_field_id'] => "value 4",
1531 'id' => $result['id'],
1532 'api.website.getValue' => array('return' => 'url'),
1533 'api.Contribution.getCount' => array(),
1534 'api.CustomValue.get' => 1,
1536 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1538 $this->customGroupDelete($ids['custom_group_id']);
1539 $this->customGroupDelete($moreids['custom_group_id']);
1540 $this->customGroupDelete($andmoreids['custom_group_id']);
1541 $this->assertEquals(1, $result['id']);
1542 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
1543 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
1546 * Test checks siusage of $values to pick & choose inputs
1548 function testChainingValuesCreate() {
1549 $description = "/*this demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
1550 2 child functions - one receives values from the parent (Contact) and the other child (Tag). ";
1551 $subfile = "APIChainedArrayValuesFromSiblingFunction";
1553 'display_name' => 'batman', 'contact_type' => 'Individual',
1554 'api.tag.create' => array('name' => '$value.id', 'description' => '$value.display_name', 'format.only_id' => 1),
1555 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
1557 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1558 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
1560 $tablesToTruncate = array(
1563 'civicrm_entity_tag',
1566 $this->quickCleanup($tablesToTruncate, TRUE);
1570 * test TrueFalse format - I couldn't come up with an easy way to get an error on Get
1572 function testContactGetFormatIsSuccessTrue() {
1573 $this->createContactFromXML();
1574 $description = "This demonstrates use of the 'format.is_success' param.
1575 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1576 $subfile = "FormatIsSuccess_True";
1577 $params = array('id' => 17, 'format.is_success' => 1);
1578 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1579 $this->assertEquals(1, $result);
1580 $this->callAPISuccess('Contact', 'Delete', $params);
1583 * test TrueFalse format
1585 function testContactCreateFormatIsSuccessFalse() {
1587 $description = "This demonstrates use of the 'format.is_success' param.
1588 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1589 $subfile = "FormatIsSuccess_Fail";
1590 $params = array('id' => 500, 'format.is_success' => 1);
1591 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1592 $this->assertEquals(0, $result);
1595 * test Single Entity format
1597 function testContactGetSingle_entity_array() {
1598 $this->createContactFromXML();
1599 $description = "This demonstrates use of the 'format.single_entity_array' param.
1600 /* This param causes the only contact to be returned as an array without the other levels.
1601 /* it will be ignored if there is not exactly 1 result";
1602 $subfile = "GetSingleContact";
1603 $params = array('id' => 17);
1604 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1605 $this->assertEquals('Test Contact', $result['display_name']);
1606 $this->callAPISuccess('Contact', 'Delete', $params);
1610 * test Single Entity format
1612 function testContactGetFormatcount_only() {
1613 $this->createContactFromXML();
1614 $description = "/*This demonstrates use of the 'getCount' action
1615 /* This param causes the count of the only function to be returned as an integer";
1616 $subfile = "GetCountContact";
1617 $params = array('id' => 17);
1618 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1619 $this->assertEquals('1', $result);
1620 $this->callAPISuccess('Contact', 'Delete', $params);
1623 * Test id only format
1625 function testContactGetFormatID_only() {
1626 $this->createContactFromXML();
1627 $description = "This demonstrates use of the 'format.id_only' param.
1628 /* This param causes the id of the only entity to be returned as an integer.
1629 /* it will be ignored if there is not exactly 1 result";
1630 $subfile = "FormatOnlyID";
1631 $params = array('id' => 17, 'format.only_id' => 1);
1632 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1633 $this->assertEquals('17', $result);
1634 $this->callAPISuccess('Contact', 'Delete', $params);
1638 * Test id only format
1640 function testContactGetFormatSingleValue() {
1641 $this->createContactFromXML();
1642 $description = "This demonstrates use of the 'format.single_value' param.
1643 /* This param causes only a single value of the only entity to be returned as an string.
1644 /* it will be ignored if there is not exactly 1 result";
1645 $subFile = "FormatSingleValue";
1646 $params = array('id' => 17, 'return' => 'display_name');
1647 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__
, __FILE__
, $description, $subFile,'getvalue');
1648 $this->assertEquals('Test Contact', $result);
1649 $this->callAPISuccess('Contact', 'Delete', $params);
1653 * test that permissions are respected when creating contacts
1655 function testContactCreationPermissions() {
1657 'contact_type' => 'Individual', 'first_name' => 'Foo',
1658 'last_name' => 'Bear',
1659 'check_permissions' => TRUE,
1661 $config = CRM_Core_Config
::singleton();
1662 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1663 $result = $this->callAPIFailure('contact', 'create', $params);
1664 $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');
1666 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'add contacts', 'import contacts');
1667 $this->callAPISuccess('contact', 'create', $params, NULL, 'overfluous permissions should be enough to create a contact');
1670 function testContactUpdatePermissions() {
1671 $params = array('contact_type' => 'Individual', 'first_name' => 'Foo', 'last_name' => 'Bear', 'check_permissions' => TRUE,);
1672 $result = $this->callAPISuccess('contact', 'create', $params);
1673 $config = CRM_Core_Config
::singleton();
1674 $params = array('id' => $result['id'], 'contact_type' => 'Individual', 'last_name' => 'Bar', 'check_permissions' => TRUE,);
1676 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1677 $result = $this->callAPIFailure('contact', 'update', $params);
1678 $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');
1680 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'add contacts', 'view all contacts', 'edit all contacts', 'import contacts');
1681 $this->callAPISuccess('contact', 'update', $params, NULL, 'overfluous permissions should be enough to update a contact');
1684 function createContactFromXML() {
1685 // Insert a row in civicrm_contact creating contact 17
1686 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1687 $op->execute($this->_dbconn
,
1688 $this->createXMLDataSet(
1689 dirname(__FILE__
) . '/dataset/contact_17.xml'
1694 function testContactProximity() {
1695 // first create a contact with a SF location with a specific
1697 $contactID = $this->organizationCreate();
1699 // now create the address
1701 'street_address' => '123 Main Street',
1702 'city' => 'San Francisco',
1704 'country_id' => 1228,
1705 'state_province_id' => 1004,
1706 'geo_code_1' => '37.79',
1707 'geo_code_2' => '-122.40',
1708 'location_type_id' => 1,
1709 'contact_id' => $contactID,
1712 $result = $this->callAPISuccess('address', 'create', $params);
1713 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1715 // now do a proximity search with a close enough geocode and hope to match
1716 // that specific contact only!
1717 $proxParams = array(
1719 'longitude' => -122.3,
1723 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
1724 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1728 * Test that Ajax API permission is sufficient to access getquick api
1729 * (note that getquick api is required for autocomplete & has ACL permissions applied)
1731 function testGetquickPermission_CRM_13744() {
1732 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviEvent');
1733 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1734 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
1735 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1736 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access AJAX API');
1737 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1741 * test get ref api - gets a list of references to an entity
1743 function testGetReferenceCounts() {
1744 $result = $this->callAPISuccess('Contact', 'create', array(
1745 'first_name' => 'Testily',
1746 'last_name' => 'McHaste',
1747 'contact_type' => 'Individual',
1748 'api.Address.replace' => array(
1749 'values' => array(),
1751 'api.Email.replace' => array(
1754 'email' => 'spam@dev.null',
1756 'location_type_id' => 1,
1760 'api.Phone.replace' => array(
1763 'phone' => '234-567-0001',
1765 'location_type_id' => 1,
1768 'phone' => '234-567-0002',
1770 'location_type_id' => 1,
1776 //$dao = new CRM_Contact_BAO_Contact();
1777 //$dao->id = $result['id'];
1778 //$this->assertTrue((bool) $dao->find(TRUE));
1780 //$refCounts = $dao->getReferenceCounts();
1781 //$this->assertTrue(is_array($refCounts));
1782 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
1784 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
1785 'id' => $result['id']
1787 $refCountsIdx = CRM_Utils_Array
::index(array('name'), $refCounts['values']);
1789 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
1790 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
1791 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
1792 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
1793 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
1796 function testSQLOperatorsOnContactAPI() {
1797 $this->individualCreate();
1798 $this->organizationCreate();
1799 $this->householdCreate();
1800 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
1801 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
1802 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
1803 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
1807 * CRM-14743 - test api respects search operators
1809 function testGetModifiedDateByOperators() {
1810 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1811 $contact1 = $this->individualCreate();
1812 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
1813 CRM_Core_DAO
::executeQuery($sql);
1814 $contact2 = $this->individualCreate();
1815 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
1816 CRM_Core_DAO
::executeQuery($sql);
1817 $contact3 = $this->householdCreate();
1818 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
1819 CRM_Core_DAO
::executeQuery($sql);
1820 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
1821 $this->assertEquals($contacts['count'], 3);
1822 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
1823 $this->assertEquals($contacts['count'], $preExistingContactCount);
1827 * CRM-14743 - test api respects search operators
1829 function testGetCreatedDateByOperators() {
1830 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1831 $contact1 = $this->individualCreate();
1832 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
1833 CRM_Core_DAO
::executeQuery($sql);
1834 $contact2 = $this->individualCreate();
1835 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
1836 CRM_Core_DAO
::executeQuery($sql);
1837 $contact3 = $this->householdCreate();
1838 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
1839 CRM_Core_DAO
::executeQuery($sql);
1840 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
1841 $this->assertEquals($contacts['count'], 3);
1842 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
1843 $this->assertEquals($contacts['count'], $preExistingContactCount);
1847 * CRM-14263 check that API is not affected by search profile related bug
1849 function testReturnCityProfile () {
1850 $contactID = $this->individualCreate();
1851 CRM_Core_Config
::singleton()->defaultSearchProfileID
= 1;
1852 $this->callAPISuccess('address', 'create', array('contact_id' => $contactID, 'city' => 'Cool City', 'location_type_id' => 1,));
1853 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
1854 $this->assertEquals(1, $result['count']);
1858 * CRM-15443 - ensure getlist api does not return deleted contacts
1860 function testGetlistExcludeConditions() {
1861 $name = md5(time());
1862 $contact = $this->individualCreate(array('last_name' => $name));
1863 $deceasedContact = $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
1864 $deletedContact = $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
1865 // We should get all but the deleted contact
1866 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
1867 $this->assertEquals(2, $result['count'], 'In line ' . __LINE__
);
1868 // Force-exclude the deceased contact
1869 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name, 'params' => array('is_deceased' => 0)));
1870 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1871 $this->assertEquals($contact, $result['values'][0]['id'], 'In line ' . __LINE__
);
1875 * Test contact.getactions
1877 function testGetActions() {
1878 $description = "Getting the available actions for an entity.";
1879 $result = $this->callAPIAndDocument($this->_entity
, 'getactions', array(), __FUNCTION__
, __FILE__
, $description);
1899 $deprecated = array(
1903 foreach ($expected as $action) {
1904 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
1906 foreach ($deprecated as $action) {
1907 $this->assertArrayKeyExists($action, $result['deprecated']);