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
1029 public function testUpdateCreateWithID() {
1030 // Insert a row in civicrm_contact creating individual contact
1031 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1032 $op->execute($this->_dbconn
,
1033 $this->createXMLDataSet(
1034 dirname(__FILE__
) . '/dataset/contact_ind.xml'
1040 'first_name' => 'abcd',
1041 'last_name' => 'wxyz',
1043 $this->callAPISuccess('Contact', 'Update', $params);
1047 * Test civicrm_contact_delete() with no contact ID
1049 public function testContactDeleteNoID() {
1053 $this->callAPIFailure('contact', 'delete', $params);
1057 * Test civicrm_contact_delete() with error
1059 public function testContactDeleteError() {
1060 $params = array('contact_id' => 999);
1061 $this->callAPIFailure('contact', 'delete', $params);
1065 * Test civicrm_contact_delete()
1067 public function testContactDelete() {
1068 $contactID = $this->individualCreate();
1072 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__
, __FILE__
);
1076 * Test civicrm_contact_get() return only first name
1078 public function testContactGetRetFirst() {
1079 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1081 'contact_id' => $contact['id'],
1082 'return_first_name' => TRUE,
1083 'sort' => 'first_name',
1085 $result = $this->callAPISuccess('contact', 'get', $params);
1086 $this->assertEquals(1, $result['count']);
1087 $this->assertEquals($contact['id'], $result['id']);
1088 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1092 * Test civicrm_contact_get() return only first name & last name
1093 * Use comma separated string return with a space
1095 public function testContactGetRetFirstLast() {
1096 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1098 'contact_id' => $contact['id'],
1099 'return' => 'first_name, last_name',
1101 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1102 $this->assertEquals('abc1', $result['first_name']);
1103 $this->assertEquals('xyz1', $result['last_name']);
1104 //check that other defaults not returns
1105 $this->assertArrayNotHasKey('sort_name', $result);
1107 'contact_id' => $contact['id'],
1108 'return' => 'first_name,last_name',
1110 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1111 $this->assertEquals('abc1', $result['first_name']);
1112 $this->assertEquals('xyz1', $result['last_name']);
1113 //check that other defaults not returns
1114 $this->assertArrayNotHasKey('sort_name', $result);
1118 * Test civicrm_contact_get() return only first name & last name
1119 * Use comma separated string return without a space
1121 public function testContactGetRetFirstLastNoComma() {
1122 $contact = $this->callAPISuccess('contact', 'create', $this->_params
);
1124 'contact_id' => $contact['id'],
1125 'return' => 'first_name,last_name',
1127 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1128 $this->assertEquals('abc1', $result['first_name']);
1129 $this->assertEquals('xyz1', $result['last_name']);
1130 //check that other defaults not returns
1131 $this->assertArrayNotHasKey('sort_name', $result);
1135 * Test civicrm_contact_get() with default return properties
1137 public function testContactGetRetDefault() {
1138 $contactID = $this->individualCreate();
1140 'contact_id' => $contactID,
1141 'sort' => 'first_name',
1143 $result = $this->callAPISuccess('contact', 'get', $params);
1144 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1145 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1149 * Test civicrm_contact_getquick() with empty name param
1151 public function testContactGetQuick() {
1152 // Insert a row in civicrm_contact creating individual contact
1153 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1154 $op->execute($this->_dbconn
,
1155 $this->createXMLDataSet(
1156 dirname(__FILE__
) . '/dataset/contact_17.xml'
1159 $op->execute($this->_dbconn
,
1160 $this->createXMLDataSet(
1161 dirname(__FILE__
) . '/dataset/email_contact_17.xml'
1168 $result = $this->callAPISuccess('contact', 'getquick', $params);
1169 $this->assertEquals(17, $result['values'][0]['id'], 'in line ' . __LINE__
);
1173 * Test civicrm_contact_get) with empty params
1175 public function testContactGetEmptyParams() {
1176 $this->callAPISuccess('contact', 'get', array());
1180 * Test civicrm_contact_get(,true) with no matches
1182 public function testContactGetOldParamsNoMatches() {
1183 // Insert a row in civicrm_contact creating contact 17
1184 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1185 $op->execute($this->_dbconn
,
1186 $this->createXMLDataSet(
1187 dirname(__FILE__
) . '/dataset/contact_17.xml'
1192 'first_name' => 'Fred',
1194 $result = $this->callAPISuccess('contact', 'get', $params);
1195 $this->assertEquals(0, $result['count'], 'in line ' . __LINE__
);
1199 * Test civicrm_contact_get(,true) with one match
1201 public function testContactGetOldParamsOneMatch() {
1202 // Insert a row in civicrm_contact creating contact 17
1203 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1204 $op->execute($this->_dbconn
,
1205 $this->createXMLDataSet(dirname(__FILE__
) . '/dataset/contact_17.xml'
1210 'first_name' => 'Test',
1212 $result = $this->callAPISuccess('contact', 'get', $params);
1213 $this->assertEquals(17, $result['values'][17]['contact_id'], 'in line ' . __LINE__
);
1214 $this->assertEquals(17, $result['id'], 'in line ' . __LINE__
);
1218 * Test civicrm_contact_search_count()
1220 public function testContactGetEmail() {
1222 'email' => 'man2@yahoo.com',
1223 'contact_type' => 'Individual',
1224 'location_type_id' => 1,
1227 $contact = $this->callAPISuccess('contact', 'create', $params);
1229 $this->assertEquals(1, $contact['id']);
1232 'email' => 'man2@yahoo.com',
1234 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__
, __FILE__
);
1235 $this->assertEquals(1, $result['values'][1]['contact_id']);
1236 $this->assertEquals('man2@yahoo.com', $result['values'][1]['email']);
1238 // delete the contact
1239 $this->callAPISuccess('contact', 'delete', $contact);
1243 * Test birth date params incl value, array & birth_date_high, birth_date_low
1246 public function testContactGetBirthDate() {
1247 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 2 years')));
1248 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month - 5 years')));
1249 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('birth_date' => 'first day of next month -20 years')));
1251 $result = $this->callAPISuccess('contact', 'get', array());
1252 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1253 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1254 $this->assertEquals(1, $result['count']);
1255 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1256 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1257 $this->assertEquals(1, $result['count']);
1258 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1259 $result = $this->callAPISuccess('contact', 'get', array(
1260 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
1261 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
1263 $this->assertEquals(1, $result['count']);
1264 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1265 $result = $this->callAPISuccess('contact', 'get', array(
1266 'birth_date_low' => '-6 years',
1267 'birth_date_high' => '- 3 years',
1269 $this->assertEquals(1, $result['count']);
1270 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1274 * Test Deceaseddate params incl value, array & Deceased_date_high, Deceaseddate_low
1277 public function testContactGetDeceasedDate() {
1278 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 2 years')));
1279 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month - 5 years')));
1280 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params
, array('deceased_date' => 'first day of next month -20 years')));
1282 $result = $this->callAPISuccess('contact', 'get', array());
1283 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
1284 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
1285 $this->assertEquals(1, $result['count']);
1286 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1287 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
1288 $this->assertEquals(1, $result['count']);
1289 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
1290 $result = $this->callAPISuccess('contact', 'get', array(
1291 'deceased_date_low' => '-6 years',
1292 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
1294 $this->assertEquals(1, $result['count']);
1295 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1299 * Test for Contact.get id=@user:username
1301 public function testContactGetByUsername() {
1302 // setup - create contact with a uf-match
1303 $cid = $this->individualCreate(array(
1304 'contact_type' => 'Individual',
1305 'first_name' => 'testGetByUsername',
1306 'last_name' => 'testGetByUsername',
1309 $ufMatchParams = array(
1310 'domain_id' => CRM_Core_Config
::domainID(),
1312 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
1313 'contact_id' => $cid,
1315 $ufMatch = CRM_Core_BAO_UFMatch
::create($ufMatchParams);
1316 $this->assertTrue(is_numeric($ufMatch->id
));
1318 // setup - mock the calls to CRM_Utils_System_*::getUfId
1319 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1320 $userSystem->expects($this->once())
1322 ->with($this->equalTo('exampleUser'))
1323 ->will($this->returnValue(99));
1324 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1327 $result = $this->callAPISuccess('Contact', 'get', array(
1328 'id' => '@user:exampleUser',
1330 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
1334 * Test to check return works OK
1336 public function testContactGetReturnValues() {
1337 $extraParams = array('nick_name' => 'Bob', 'phone' => '456', 'email' => 'e@mail.com');
1338 $contactID = $this->individualCreate($extraParams);
1339 //actually it turns out the above doesn't create a phone
1340 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
1341 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
1342 foreach ($extraParams as $key => $value) {
1343 $this->assertEquals($result[$key], $value);
1345 //now we check they are still returned with 'return' key
1346 $result = $this->callAPISuccess('contact', 'getsingle', array(
1348 'return' => array_keys($extraParams),
1350 foreach ($extraParams as $key => $value) {
1351 $this->assertEquals($result[$key], $value);
1355 public function testCRM13252MultipleChainedPhones() {
1356 $contactID = $this->householdCreate();
1357 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
1359 'contact_id' => $contactID,
1360 'household_name' => 'Household 1',
1361 'contact_type' => 'Household',
1362 'api.phone.create' => array(
1364 'phone' => '111-111-1111',
1365 'location_type_id' => 1,
1366 'phone_type_id' => 1,
1369 'phone' => '222-222-2222',
1370 'location_type_id' => 1,
1371 'phone_type_id' => 2,
1375 $this->callAPISuccess('contact', 'create', $params);
1376 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
1381 * Test for Contact.get id=@user:username (with an invalid username)
1383 public function testContactGetByUnknownUsername() {
1384 // setup - mock the calls to CRM_Utils_System_*::getUfId
1385 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
1386 $userSystem->expects($this->once())
1388 ->with($this->equalTo('exampleUser'))
1389 ->will($this->returnValue(NULL));
1390 CRM_Core_Config
::singleton()->userSystem
= $userSystem;
1393 $result = $this->callAPIFailure('Contact', 'get', array(
1394 'id' => '@user:exampleUser',
1396 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
1400 * Verify attempt to create individual with chained arrays
1402 public function testGetIndividualWithChainedArrays() {
1403 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1404 $params['custom_' . $ids['custom_field_id']] = "custom string";
1406 $moreids = $this->CustomGroupMultipleCreateWithFields();
1407 $description = "/*this demonstrates the usage of chained api functions. In this case no notes or custom fields have been created ";
1408 $subfile = "APIChainedArray";
1410 'first_name' => 'abc3',
1411 'last_name' => 'xyz3',
1412 'contact_type' => 'Individual',
1413 'email' => 'man3@yahoo.com',
1414 'api.contribution.create' => array(
1415 'receive_date' => '2010-01-01',
1416 'total_amount' => 100.00,
1417 'financial_type_id' => 1,
1418 'payment_instrument_id' => 1,
1419 'non_deductible_amount' => 10.00,
1420 'fee_amount' => 50.00,
1421 'net_amount' => 90.00,
1423 'invoice_id' => 67890,
1425 'contribution_status_id' => 1,
1427 'api.contribution.create.1' => array(
1428 'receive_date' => '2011-01-01',
1429 'total_amount' => 120.00,
1430 'financial_type_id' => $this->_financialTypeId
= 1,
1431 'payment_instrument_id' => 1,
1432 'non_deductible_amount' => 10.00,
1433 'fee_amount' => 50.00,
1434 'net_amount' => 90.00,
1436 'invoice_id' => 67830,
1438 'contribution_status_id' => 1,
1440 'api.website.create' => array(
1442 'url' => "http://civicrm.org",
1447 $result = $this->callAPISuccess('Contact', 'create', $params);
1449 'id' => $result['id'],
1450 'api.website.get' => array(),
1451 'api.Contribution.get' => array(
1452 'total_amount' => '120.00',
1454 'api.CustomValue.get' => 1,
1455 'api.Note.get' => 1,
1457 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1458 // delete the contact
1459 $this->callAPISuccess('contact', 'delete', $result);
1460 $this->customGroupDelete($ids['custom_group_id']);
1461 $this->customGroupDelete($moreids['custom_group_id']);
1462 $this->assertEquals(1, $result['id']);
1463 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
1464 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
1467 public function testGetIndividualWithChainedArraysFormats() {
1468 $description = "/*this demonstrates the usage of chained api functions. A variety of return formats are used. Note that no notes
1469 *custom fields or memberships exist";
1470 $subfile = "APIChainedArrayFormats";
1471 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1472 $params['custom_' . $ids['custom_field_id']] = "custom string";
1474 $moreids = $this->CustomGroupMultipleCreateWithFields();
1476 'first_name' => 'abc3',
1477 'last_name' => 'xyz3',
1478 'contact_type' => 'Individual',
1479 'email' => 'man3@yahoo.com',
1480 'api.contribution.create' => array(
1481 'receive_date' => '2010-01-01',
1482 'total_amount' => 100.00,
1483 'financial_type_id' => $this->_financialTypeId
,
1484 'payment_instrument_id' => 1,
1485 'non_deductible_amount' => 10.00,
1486 'fee_amount' => 50.00,
1487 'net_amount' => 90.00,
1489 'contribution_status_id' => 1,
1491 'api.contribution.create.1' => array(
1492 'receive_date' => '2011-01-01',
1493 'total_amount' => 120.00,
1494 'financial_type_id' => $this->_financialTypeId
,
1495 'payment_instrument_id' => 1,
1496 'non_deductible_amount' => 10.00,
1497 'fee_amount' => 50.00,
1498 'net_amount' => 90.00,
1500 'contribution_status_id' => 1,
1502 'api.website.create' => array(
1504 'url' => "http://civicrm.org",
1509 $result = $this->callAPISuccess('Contact', 'create', $params);
1511 'id' => $result['id'],
1512 'api.website.getValue' => array('return' => 'url'),
1513 'api.Contribution.getCount' => array(),
1514 'api.CustomValue.get' => 1,
1515 'api.Note.get' => 1,
1516 'api.Membership.getCount' => array(),
1518 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1519 $this->assertEquals(1, $result['id']);
1520 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
1521 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
1522 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
1524 $this->callAPISuccess('contact', 'delete', $result);
1525 $this->customGroupDelete($ids['custom_group_id']);
1526 $this->customGroupDelete($moreids['custom_group_id']);
1529 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
1530 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, __FILE__
);
1531 $params['custom_' . $ids['custom_field_id']] = "custom string";
1532 $moreids = $this->CustomGroupMultipleCreateWithFields();
1533 $andmoreids = $this->CustomGroupMultipleCreateWithFields(array(
1534 'title' => "another group",
1535 'name' => 'another name',
1537 $description = "/*this demonstrates the usage of chained api functions. A variety of techniques are used";
1538 $subfile = "APIChainedArrayMultipleCustom";
1540 'first_name' => 'abc3',
1541 'last_name' => 'xyz3',
1542 'contact_type' => 'Individual',
1543 'email' => 'man3@yahoo.com',
1544 'api.contribution.create' => array(
1545 'receive_date' => '2010-01-01',
1546 'total_amount' => 100.00,
1547 'financial_type_id' => 1,
1548 'payment_instrument_id' => 1,
1549 'non_deductible_amount' => 10.00,
1550 'fee_amount' => 50.00,
1551 'net_amount' => 90.00,
1553 'invoice_id' => 67890,
1555 'contribution_status_id' => 1,
1557 'api.contribution.create.1' => array(
1558 'receive_date' => '2011-01-01',
1559 'total_amount' => 120.00,
1560 'financial_type_id' => 1,
1561 'payment_instrument_id' => 1,
1562 'non_deductible_amount' => 10.00,
1563 'fee_amount' => 50.00,
1564 'net_amount' => 90.00,
1566 'invoice_id' => 67830,
1568 'contribution_status_id' => 1,
1570 'api.website.create' => array(
1572 'url' => "http://civicrm.org",
1575 'custom_' . $ids['custom_field_id'] => "value 1",
1576 'custom_' . $moreids['custom_field_id'][0] => "value 2",
1577 'custom_' . $moreids['custom_field_id'][1] => "warm beer",
1578 'custom_' . $andmoreids['custom_field_id'][1] => "vegemite",
1581 $result = $this->callAPISuccess('Contact', 'create', $params);
1582 $result = $this->callAPISuccess('Contact', 'create', array(
1583 'contact_type' => 'Individual',
1584 'id' => $result['id'],
1586 $moreids['custom_field_id'][0] => "value 3",
1588 $ids['custom_field_id'] => "value 4",
1592 'id' => $result['id'],
1593 'api.website.getValue' => array('return' => 'url'),
1594 'api.Contribution.getCount' => array(),
1595 'api.CustomValue.get' => 1,
1597 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1599 $this->customGroupDelete($ids['custom_group_id']);
1600 $this->customGroupDelete($moreids['custom_group_id']);
1601 $this->customGroupDelete($andmoreids['custom_group_id']);
1602 $this->assertEquals(1, $result['id']);
1603 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
1604 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
1608 * Test checks siusage of $values to pick & choose inputs
1610 public function testChainingValuesCreate() {
1611 $description = "/*this demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
1612 2 child functions - one receives values from the parent (Contact) and the other child (Tag). ";
1613 $subfile = "APIChainedArrayValuesFromSiblingFunction";
1615 'display_name' => 'batman',
1616 'contact_type' => 'Individual',
1617 'api.tag.create' => array('name' => '$value.id', 'description' => '$value.display_name', 'format.only_id' => 1),
1618 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
1620 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1621 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
1623 $tablesToTruncate = array(
1626 'civicrm_entity_tag',
1629 $this->quickCleanup($tablesToTruncate, TRUE);
1633 * test TrueFalse format - I couldn't come up with an easy way to get an error on Get
1635 public function testContactGetFormatIsSuccessTrue() {
1636 $this->createContactFromXML();
1637 $description = "This demonstrates use of the 'format.is_success' param.
1638 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1639 $subfile = "FormatIsSuccess_True";
1640 $params = array('id' => 17, 'format.is_success' => 1);
1641 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1642 $this->assertEquals(1, $result);
1643 $this->callAPISuccess('Contact', 'Delete', $params);
1647 * test TrueFalse format
1649 public function testContactCreateFormatIsSuccessFalse() {
1651 $description = "This demonstrates use of the 'format.is_success' param.
1652 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
1653 $subfile = "FormatIsSuccess_Fail";
1654 $params = array('id' => 500, 'format.is_success' => 1);
1655 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1656 $this->assertEquals(0, $result);
1660 * test Single Entity format
1662 public function testContactGetSingle_entity_array() {
1663 $this->createContactFromXML();
1664 $description = "This demonstrates use of the 'format.single_entity_array' param.
1665 /* This param causes the only contact to be returned as an array without the other levels.
1666 /* it will be ignored if there is not exactly 1 result";
1667 $subfile = "GetSingleContact";
1668 $params = array('id' => 17);
1669 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1670 $this->assertEquals('Test Contact', $result['display_name']);
1671 $this->callAPISuccess('Contact', 'Delete', $params);
1675 * test Single Entity format
1677 public function testContactGetFormatcount_only() {
1678 $this->createContactFromXML();
1679 $description = "/*This demonstrates use of the 'getCount' action
1680 /* This param causes the count of the only function to be returned as an integer";
1681 $subfile = "GetCountContact";
1682 $params = array('id' => 17);
1683 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1684 $this->assertEquals('1', $result);
1685 $this->callAPISuccess('Contact', 'Delete', $params);
1689 * Test id only format
1691 public function testContactGetFormatID_only() {
1692 $this->createContactFromXML();
1693 $description = "This demonstrates use of the 'format.id_only' param.
1694 /* This param causes the id of the only entity to be returned as an integer.
1695 /* it will be ignored if there is not exactly 1 result";
1696 $subfile = "FormatOnlyID";
1697 $params = array('id' => 17, 'format.only_id' => 1);
1698 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__
, __FILE__
, $description, $subfile);
1699 $this->assertEquals('17', $result);
1700 $this->callAPISuccess('Contact', 'Delete', $params);
1704 * Test id only format
1706 public function testContactGetFormatSingleValue() {
1707 $this->createContactFromXML();
1708 $description = "This demonstrates use of the 'format.single_value' param.
1709 /* This param causes only a single value of the only entity to be returned as an string.
1710 /* it will be ignored if there is not exactly 1 result";
1711 $subFile = "FormatSingleValue";
1712 $params = array('id' => 17, 'return' => 'display_name');
1713 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__
, __FILE__
, $description, $subFile, 'getvalue');
1714 $this->assertEquals('Test Contact', $result);
1715 $this->callAPISuccess('Contact', 'Delete', $params);
1719 * Test that permissions are respected when creating contacts
1721 public function testContactCreationPermissions() {
1723 'contact_type' => 'Individual',
1724 'first_name' => 'Foo',
1725 'last_name' => 'Bear',
1726 'check_permissions' => TRUE,
1728 $config = CRM_Core_Config
::singleton();
1729 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1730 $result = $this->callAPIFailure('contact', 'create', $params);
1731 $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');
1733 $config->userPermissionClass
->permissions
= array('access CiviCRM', 'add contacts', 'import contacts');
1734 $this->callAPISuccess('contact', 'create', $params, NULL, 'overfluous permissions should be enough to create a contact');
1737 public function testContactUpdatePermissions() {
1739 'contact_type' => 'Individual',
1740 'first_name' => 'Foo',
1741 'last_name' => 'Bear',
1742 'check_permissions' => TRUE,
1744 $result = $this->callAPISuccess('contact', 'create', $params);
1745 $config = CRM_Core_Config
::singleton();
1747 'id' => $result['id'],
1748 'contact_type' => 'Individual',
1749 'last_name' => 'Bar',
1750 'check_permissions' => TRUE,
1753 $config->userPermissionClass
->permissions
= array('access CiviCRM');
1754 $result = $this->callAPIFailure('contact', 'update', $params);
1755 $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');
1757 $config->userPermissionClass
->permissions
= array(
1760 'view all contacts',
1761 'edit all contacts',
1764 $this->callAPISuccess('contact', 'update', $params, NULL, 'overfluous permissions should be enough to update a contact');
1767 public function createContactFromXML() {
1768 // Insert a row in civicrm_contact creating contact 17
1769 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1770 $op->execute($this->_dbconn
,
1771 $this->createXMLDataSet(
1772 dirname(__FILE__
) . '/dataset/contact_17.xml'
1777 public function testContactProximity() {
1778 // first create a contact with a SF location with a specific
1780 $contactID = $this->organizationCreate();
1782 // now create the address
1784 'street_address' => '123 Main Street',
1785 'city' => 'San Francisco',
1787 'country_id' => 1228,
1788 'state_province_id' => 1004,
1789 'geo_code_1' => '37.79',
1790 'geo_code_2' => '-122.40',
1791 'location_type_id' => 1,
1792 'contact_id' => $contactID,
1795 $result = $this->callAPISuccess('address', 'create', $params);
1796 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1798 // now do a proximity search with a close enough geocode and hope to match
1799 // that specific contact only!
1800 $proxParams = array(
1802 'longitude' => -122.3,
1806 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
1807 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1811 * Test that Ajax API permission is sufficient to access getquick api
1812 * (note that getquick api is required for autocomplete & has ACL permissions applied)
1814 public function testGetquickPermission_CRM_13744() {
1815 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviEvent');
1816 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1817 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access CiviCRM');
1818 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1819 CRM_Core_Config
::singleton()->userPermissionClass
->permissions
= array('access AJAX API');
1820 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
1824 * Test get ref api - gets a list of references to an entity
1826 public function testGetReferenceCounts() {
1827 $result = $this->callAPISuccess('Contact', 'create', array(
1828 'first_name' => 'Testily',
1829 'last_name' => 'McHaste',
1830 'contact_type' => 'Individual',
1831 'api.Address.replace' => array(
1832 'values' => array(),
1834 'api.Email.replace' => array(
1837 'email' => 'spam@dev.null',
1839 'location_type_id' => 1,
1843 'api.Phone.replace' => array(
1846 'phone' => '234-567-0001',
1848 'location_type_id' => 1,
1851 'phone' => '234-567-0002',
1853 'location_type_id' => 1,
1859 //$dao = new CRM_Contact_BAO_Contact();
1860 //$dao->id = $result['id'];
1861 //$this->assertTrue((bool) $dao->find(TRUE));
1863 //$refCounts = $dao->getReferenceCounts();
1864 //$this->assertTrue(is_array($refCounts));
1865 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
1867 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
1868 'id' => $result['id'],
1870 $refCountsIdx = CRM_Utils_Array
::index(array('name'), $refCounts['values']);
1872 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
1873 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
1874 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
1875 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
1876 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
1879 public function testSQLOperatorsOnContactAPI() {
1880 $this->individualCreate();
1881 $this->organizationCreate();
1882 $this->householdCreate();
1883 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
1884 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
1885 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
1886 $this->assertEquals($contacts['count'], CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
1890 * CRM-14743 - test api respects search operators
1892 public function testGetModifiedDateByOperators() {
1893 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1894 $contact1 = $this->individualCreate();
1895 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
1896 CRM_Core_DAO
::executeQuery($sql);
1897 $contact2 = $this->individualCreate();
1898 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
1899 CRM_Core_DAO
::executeQuery($sql);
1900 $contact3 = $this->householdCreate();
1901 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
1902 CRM_Core_DAO
::executeQuery($sql);
1903 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
1904 $this->assertEquals($contacts['count'], 3);
1905 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
1906 $this->assertEquals($contacts['count'], $preExistingContactCount);
1910 * CRM-14743 - test api respects search operators
1912 public function testGetCreatedDateByOperators() {
1913 $preExistingContactCount = CRM_Core_DAO
::singleValueQuery('select count(*) FROM civicrm_contact');
1914 $contact1 = $this->individualCreate();
1915 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
1916 CRM_Core_DAO
::executeQuery($sql);
1917 $contact2 = $this->individualCreate();
1918 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
1919 CRM_Core_DAO
::executeQuery($sql);
1920 $contact3 = $this->householdCreate();
1921 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
1922 CRM_Core_DAO
::executeQuery($sql);
1923 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
1924 $this->assertEquals($contacts['count'], 3);
1925 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
1926 $this->assertEquals($contacts['count'], $preExistingContactCount);
1930 * CRM-14263 check that API is not affected by search profile related bug
1932 public function testReturnCityProfile() {
1933 $contactID = $this->individualCreate();
1934 CRM_Core_Config
::singleton()->defaultSearchProfileID
= 1;
1935 $this->callAPISuccess('address', 'create', array(
1936 'contact_id' => $contactID,
1937 'city' => 'Cool City',
1938 'location_type_id' => 1,
1940 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
1941 $this->assertEquals(1, $result['count']);
1945 * CRM-15443 - ensure getlist api does not return deleted contacts
1947 public function testGetlistExcludeConditions() {
1948 $name = md5(time());
1949 $contact = $this->individualCreate(array('last_name' => $name));
1950 $deceasedContact = $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
1951 $deletedContact = $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
1952 // We should get all but the deleted contact
1953 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
1954 $this->assertEquals(2, $result['count'], 'In line ' . __LINE__
);
1955 // Force-exclude the deceased contact
1956 $result = $this->callAPISuccess('contact', 'getlist', array(
1958 'params' => array('is_deceased' => 0),
1960 $this->assertEquals(1, $result['count'], 'In line ' . __LINE__
);
1961 $this->assertEquals($contact, $result['values'][0]['id'], 'In line ' . __LINE__
);
1965 * Test contact.getactions
1967 public function testGetActions() {
1968 $description = "Getting the available actions for an entity.";
1969 $result = $this->callAPIAndDocument($this->_entity
, 'getactions', array(), __FUNCTION__
, __FILE__
, $description);
1989 $deprecated = array(
1993 foreach ($expected as $action) {
1994 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
1996 foreach ($deprecated as $action) {
1997 $this->assertArrayKeyExists($action, $result['deprecated']);