Merge pull request #11735 from mukeshcompucorp/CRM-21814-add-proper-container-to...
[civicrm-core.git] / tests / phpunit / api / v3 / ContactTest.php
1 <?php
2 /**
3 * @file
4 * File for the TestContact class.
5 *
6 * (PHP 5)
7 *
8 * @author Walt Haas <walt@dharmatech.org> (801) 534-1262
9 * @copyright Copyright CiviCRM LLC (C) 2009
10 * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html
11 * GNU Affero General Public License version 3
12 * @version $Id: ContactTest.php 31254 2010-12-15 10:09:29Z eileen $
13 * @package CiviCRM
14 *
15 * This file is part of CiviCRM
16 *
17 * CiviCRM is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU Affero General Public License
19 * as published by the Free Software Foundation; either version 3 of
20 * the License, or (at your option) any later version.
21 *
22 * CiviCRM is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU Affero General Public License for more details.
26 *
27 * You should have received a copy of the GNU Affero General Public
28 * License along with this program. If not, see
29 * <http://www.gnu.org/licenses/>.
30 */
31
32 /**
33 * Test APIv3 civicrm_contact* functions
34 *
35 * @package CiviCRM_APIv3
36 * @subpackage API_Contact
37 * @group headless
38 */
39 class api_v3_ContactTest extends CiviUnitTestCase {
40 public $DBResetRequired = FALSE;
41 protected $_apiversion;
42 protected $_entity;
43 protected $_params;
44
45 protected $_contactID;
46 protected $_financialTypeId = 1;
47
48 /**
49 * Test setup for every test.
50 *
51 * Connect to the database, truncate the tables that will be used
52 * and redirect stdin to a temporary file
53 */
54 public function setUp() {
55 // Connect to the database.
56 parent::setUp();
57 $this->_apiversion = 3;
58 $this->_entity = 'contact';
59 $this->_params = array(
60 'first_name' => 'abc1',
61 'contact_type' => 'Individual',
62 'last_name' => 'xyz1',
63 );
64 }
65
66 /**
67 * Restore the DB for the next test.
68 *
69 * @throws \Exception
70 */
71 public function tearDown() {
72 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
73 // truncate a few tables
74 $tablesToTruncate = array(
75 'civicrm_email',
76 'civicrm_contribution',
77 'civicrm_line_item',
78 'civicrm_website',
79 'civicrm_relationship',
80 'civicrm_uf_match',
81 'civicrm_phone',
82 'civicrm_address',
83 'civicrm_acl_contact_cache',
84 'civicrm_activity_contact',
85 'civicrm_activity',
86 'civicrm_group',
87 'civicrm_group_contact',
88 'civicrm_saved_search',
89 'civicrm_group_contact_cache',
90 );
91
92 $this->quickCleanup($tablesToTruncate, TRUE);
93 parent::tearDown();
94 }
95
96 /**
97 * Test civicrm_contact_create.
98 *
99 * Verify that attempt to create individual contact with only
100 * first and last names succeeds
101 */
102 public function testAddCreateIndividual() {
103 $oldCount = CRM_Core_DAO::singleValueQuery('select count(*) from civicrm_contact');
104 $params = array(
105 'first_name' => 'abc1',
106 'contact_type' => 'Individual',
107 'last_name' => 'xyz1',
108 );
109
110 $contact = $this->callAPISuccess('contact', 'create', $params);
111 $this->assertTrue(is_numeric($contact['id']));
112 $this->assertTrue($contact['id'] > 0);
113 $newCount = CRM_Core_DAO::singleValueQuery('select count(*) from civicrm_contact');
114 $this->assertEquals($oldCount + 1, $newCount);
115
116 $this->assertDBState('CRM_Contact_DAO_Contact',
117 $contact['id'],
118 $params
119 );
120 }
121
122 /**
123 * Test that it is possible to prevent cache clearing via option.
124 *
125 * Cache clearing is bypassed if 'options' => array('do_not_reset_cache' => 1 is used.
126 */
127 public function testCreateIndividualNoCacheClear() {
128
129 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
130 $groupID = $this->groupCreate();
131
132 $this->putGroupContactCacheInClearableState($groupID, $contact);
133
134 $this->callAPISuccess('contact', 'create', array('id' => $contact['id']));
135 $this->assertEquals(0, CRM_Core_DAO::singleValueQuery("SELECT count(*) FROM civicrm_group_contact_cache"));
136
137 // Rinse & repeat, but with the option.
138 $this->putGroupContactCacheInClearableState($groupID, $contact);
139 CRM_Core_Config::setPermitCacheFlushMode(FALSE);
140 $this->callAPISuccess('contact', 'create', array('id' => $contact['id']));
141 $this->assertEquals(1, CRM_Core_DAO::singleValueQuery("SELECT count(*) FROM civicrm_group_contact_cache"));
142 CRM_Core_Config::setPermitCacheFlushMode(TRUE);
143 }
144
145 /**
146 * Test for international string acceptance (CRM-10210).
147 *
148 * @dataProvider getInternationalStrings
149 *
150 * @param string $string
151 * String to be tested.
152 *
153 * @throws \Exception
154 */
155 public function testInternationalStrings($string) {
156 $this->callAPISuccess('Contact', 'create', array_merge(
157 $this->_params,
158 array('first_name' => $string)
159 ));
160 $result = $this->callAPISuccessGetSingle('Contact', array('first_name' => $string));
161 $this->assertEquals($string, $result['first_name']);
162
163 $organizationParams = array(
164 'organization_name' => $string,
165 'contact_type' => 'Organization',
166 );
167
168 $this->callAPISuccess('Contact', 'create', $organizationParams);
169 $result = $this->callAPISuccessGetSingle('Contact', $organizationParams);
170 $this->assertEquals($string, $result['organization_name']);
171 }
172
173 /**
174 * Get international string data for testing against api calls.
175 */
176 public function getInternationalStrings() {
177 $invocations = array();
178 $invocations[] = array('Scarabée');
179 $invocations[] = array('Iñtërnâtiônàlizætiøn');
180 $invocations[] = array('これは日本語のテキストです。読めますか');
181 $invocations[] = array('देखें हिन्दी कैसी नजर आती है। अरे वाह ये तो नजर आती है।');
182 return $invocations;
183 }
184
185 /**
186 * Test civicrm_contact_create.
187 *
188 * Verify that preferred language can be set.
189 */
190 public function testAddCreateIndividualWithPreferredLanguage() {
191 $params = array(
192 'first_name' => 'abc1',
193 'contact_type' => 'Individual',
194 'last_name' => 'xyz1',
195 'preferred_language' => 'es_ES',
196 );
197
198 $contact = $this->callAPISuccess('contact', 'create', $params);
199 $this->getAndCheck($params, $contact['id'], 'Contact');
200 }
201
202 /**
203 * Test civicrm_contact_create with sub-types.
204 *
205 * Verify that sub-types are created successfully and not deleted by subsequent updates.
206 */
207 public function testIndividualSubType() {
208 $params = array(
209 'first_name' => 'test abc',
210 'contact_type' => 'Individual',
211 'last_name' => 'test xyz',
212 'contact_sub_type' => array('Student', 'Staff'),
213 );
214 $contact = $this->callAPISuccess('contact', 'create', $params);
215 $cid = $contact['id'];
216
217 $params = array(
218 'id' => $cid,
219 'middle_name' => 'foo',
220 );
221 $this->callAPISuccess('contact', 'create', $params);
222 unset($params['middle_name']);
223
224 $contact = $this->callAPISuccess('contact', 'get', $params);
225
226 $this->assertEquals(array('Student', 'Staff'), $contact['values'][$cid]['contact_sub_type']);
227 }
228
229 /**
230 * Verify that we can retreive contacts of different sub types
231 */
232 public function testGetMultipleContactSubTypes() {
233
234 // This test presumes that there are no parents or students in the dataset
235
236 // create a student
237 $student = $this->callAPISuccess('contact', 'create', array(
238 'email' => 'student@example.com',
239 'contact_type' => 'Individual',
240 'contact_sub_type' => 'Student',
241 ));
242
243 // create a parent
244 $parent = $this->callAPISuccess('contact', 'create', array(
245 'email' => 'parent@example.com',
246 'contact_type' => 'Individual',
247 'contact_sub_type' => 'Parent',
248 ));
249
250 // create a parent
251 $contact = $this->callAPISuccess('contact', 'create', array(
252 'email' => 'parent@example.com',
253 'contact_type' => 'Individual',
254 ));
255
256 // get all students and parents
257 $getParams = array('contact_sub_type' => array('IN' => array('Parent', 'Student')));
258 $result = civicrm_api3('contact', 'get', $getParams);
259
260 // check that we retrieved the student and the parent
261 $this->assertArrayHasKey($student['id'], $result['values']);
262 $this->assertArrayHasKey($parent['id'], $result['values']);
263 $this->assertEquals(2, $result['count']);
264
265 }
266
267 /**
268 * Verify that attempt to create contact with empty params fails.
269 */
270 public function testCreateEmptyContact() {
271 $this->callAPIFailure('contact', 'create', array());
272 }
273
274 /**
275 * Verify that attempt to create contact with bad contact type fails.
276 */
277 public function testCreateBadTypeContact() {
278 $params = array(
279 'email' => 'man1@yahoo.com',
280 'contact_type' => 'Does not Exist',
281 );
282 $this->callAPIFailure('contact', 'create', $params, "'Does not Exist' is not a valid option for field contact_type");
283 }
284
285 /**
286 * Verify that attempt to create individual contact without required fields fails.
287 */
288 public function testCreateBadRequiredFieldsIndividual() {
289 $params = array(
290 'middle_name' => 'This field is not required',
291 'contact_type' => 'Individual',
292 );
293 $this->callAPIFailure('contact', 'create', $params);
294 }
295
296 /**
297 * Verify that attempt to create household contact without required fields fails.
298 */
299 public function testCreateBadRequiredFieldsHousehold() {
300 $params = array(
301 'middle_name' => 'This field is not required',
302 'contact_type' => 'Household',
303 );
304 $this->callAPIFailure('contact', 'create', $params);
305 }
306
307 /**
308 * Test required field check.
309 *
310 * Verify that attempt to create organization contact without required fields fails.
311 */
312 public function testCreateBadRequiredFieldsOrganization() {
313 $params = array(
314 'middle_name' => 'This field is not required',
315 'contact_type' => 'Organization',
316 );
317
318 $this->callAPIFailure('contact', 'create', $params);
319 }
320
321 /**
322 * Verify that attempt to create individual contact with only an email succeeds.
323 */
324 public function testCreateEmailIndividual() {
325 $primaryEmail = 'man3@yahoo.com';
326 $notPrimaryEmail = 'man4@yahoo.com';
327 $params = array(
328 'email' => $primaryEmail,
329 'contact_type' => 'Individual',
330 'location_type_id' => 1,
331 );
332
333 $contact1 = $this->callAPISuccess('contact', 'create', $params);
334
335 $this->assertEquals(3, $contact1['id']);
336 $email1 = $this->callAPISuccess('email', 'get', array('contact_id' => $contact1['id']));
337 $this->assertEquals(1, $email1['count']);
338 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
339
340 $email2 = $this->callAPISuccess('email', 'create', array('contact_id' => $contact1['id'], 'is_primary' => 0, 'email' => $notPrimaryEmail));
341
342 // Case 1: Check with criteria primary 'email' => array('IS NOT NULL' => 1)
343 $result = $this->callAPISuccess('contact', 'get', array('email' => array('IS NOT NULL' => 1)));
344 $primaryEmailContactIds = array_keys($result['values']);
345 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
346
347 // Case 2: Check with criteria primary 'email' => array('<>' => '')
348 $result = $this->callAPISuccess('contact', 'get', array('email' => array('<>' => '')));
349 $primaryEmailContactIds = array_keys($result['values']);
350 $this->assertEquals($primaryEmail, $email1['values'][$email1['id']]['email']);
351
352 // Case 3: Check with email_id='primary email id'
353 $result = $this->callAPISuccess('contact', 'get', array('email_id' => $email1['id']));
354 $this->assertEquals(1, $result['count']);
355 $this->assertEquals($contact1['id'], $result['id']);
356
357 $this->callAPISuccess('contact', 'delete', $contact1);
358 }
359
360 /**
361 * Test creating individual by name.
362 *
363 * Verify create individual contact with only first and last names succeeds.
364 */
365 public function testCreateNameIndividual() {
366 $params = array(
367 'first_name' => 'abc1',
368 'contact_type' => 'Individual',
369 'last_name' => 'xyz1',
370 );
371
372 $this->callAPISuccess('contact', 'create', $params);
373 }
374
375 /**
376 * Test creating individual by display_name.
377 *
378 * Display name & sort name should be set.
379 */
380 public function testCreateDisplayNameIndividual() {
381 $params = array(
382 'display_name' => 'abc1',
383 'contact_type' => 'Individual',
384 );
385
386 $contact = $this->callAPISuccess('contact', 'create', $params);
387 $params['sort_name'] = 'abc1';
388 $this->getAndCheck($params, $contact['id'], 'contact');
389 }
390
391 /**
392 * Test old keys still work.
393 *
394 * Verify that attempt to create individual contact with
395 * first and last names and old key values works
396 */
397 public function testCreateNameIndividualOldKeys() {
398 $params = array(
399 'individual_prefix' => 'Dr.',
400 'first_name' => 'abc1',
401 'contact_type' => 'Individual',
402 'last_name' => 'xyz1',
403 'individual_suffix' => 'Jr.',
404 );
405
406 $contact = $this->callAPISuccess('contact', 'create', $params);
407 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
408
409 $this->assertArrayKeyExists('prefix_id', $result);
410 $this->assertArrayKeyExists('suffix_id', $result);
411 $this->assertArrayKeyExists('gender_id', $result);
412 $this->assertEquals(4, $result['prefix_id']);
413 $this->assertEquals(1, $result['suffix_id']);
414 }
415
416 /**
417 * Test preferred keys work.
418 *
419 * Verify that attempt to create individual contact with
420 * first and last names and old key values works
421 */
422 public function testCreateNameIndividualRecommendedKeys2() {
423 $params = array(
424 'prefix_id' => 'Dr.',
425 'first_name' => 'abc1',
426 'contact_type' => 'Individual',
427 'last_name' => 'xyz1',
428 'suffix_id' => 'Jr.',
429 'gender_id' => 'Male',
430 );
431
432 $contact = $this->callAPISuccess('contact', 'create', $params);
433 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
434
435 $this->assertArrayKeyExists('prefix_id', $result);
436 $this->assertArrayKeyExists('suffix_id', $result);
437 $this->assertArrayKeyExists('gender_id', $result);
438 $this->assertEquals(4, $result['prefix_id']);
439 $this->assertEquals(1, $result['suffix_id']);
440 }
441
442 /**
443 * Test household name is sufficient for create.
444 *
445 * Verify that attempt to create household contact with only
446 * household name succeeds
447 */
448 public function testCreateNameHousehold() {
449 $params = array(
450 'household_name' => 'The abc Household',
451 'contact_type' => 'Household',
452 );
453 $this->callAPISuccess('contact', 'create', $params);
454 }
455
456 /**
457 * Test organization name is sufficient for create.
458 *
459 * Verify that attempt to create organization contact with only
460 * organization name succeeds.
461 */
462 public function testCreateNameOrganization() {
463 $params = array(
464 'organization_name' => 'The abc Organization',
465 'contact_type' => 'Organization',
466 );
467 $this->callAPISuccess('contact', 'create', $params);
468 }
469
470 /**
471 * Verify that attempt to create organization contact without organization name fails.
472 */
473 public function testCreateNoNameOrganization() {
474 $params = array(
475 'first_name' => 'The abc Organization',
476 'contact_type' => 'Organization',
477 );
478 $this->callAPIFailure('contact', 'create', $params);
479 }
480
481 /**
482 * Check that permissions on API key are restricted (CRM-18112).
483 */
484 public function testCreateApiKey() {
485 $config = CRM_Core_Config::singleton();
486 $contactId = $this->individualCreate(array(
487 'first_name' => 'A',
488 'last_name' => 'B',
489 ));
490
491 // Allow edit -- because permissions aren't being checked
492 $config->userPermissionClass->permissions = array();
493 $result = $this->callAPISuccess('Contact', 'create', array(
494 'id' => $contactId,
495 'api_key' => 'original',
496 ));
497 $this->assertEquals('original', $result['values'][$contactId]['api_key']);
498
499 // Allow edit -- because we have adequate permission
500 $config->userPermissionClass->permissions = array('access CiviCRM', 'edit all contacts', 'edit api keys');
501 $result = $this->callAPISuccess('Contact', 'create', array(
502 'check_permissions' => 1,
503 'id' => $contactId,
504 'api_key' => 'abcd1234',
505 ));
506 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
507
508 // Disallow edit -- because we don't have permission
509 $config->userPermissionClass->permissions = array('access CiviCRM', 'edit all contacts');
510 $result = $this->callAPIFailure('Contact', 'create', array(
511 'check_permissions' => 1,
512 'id' => $contactId,
513 'api_key' => 'defg4321',
514 ));
515 $this->assertRegExp(';Permission denied to modify api key;', $result['error_message']);
516
517 // Return everything -- because permissions are not being checked
518 $config->userPermissionClass->permissions = array();
519 $result = $this->callAPISuccess('Contact', 'create', array(
520 'id' => $contactId,
521 'first_name' => 'A2',
522 ));
523 $this->assertEquals('A2', $result['values'][$contactId]['first_name']);
524 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
525 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
526
527 // Return everything -- because we have adequate permission
528 $config->userPermissionClass->permissions = array('access CiviCRM', 'edit all contacts', 'edit api keys');
529 $result = $this->callAPISuccess('Contact', 'create', array(
530 'check_permissions' => 1,
531 'id' => $contactId,
532 'first_name' => 'A3',
533 ));
534 $this->assertEquals('A3', $result['values'][$contactId]['first_name']);
535 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
536 $this->assertEquals('abcd1234', $result['values'][$contactId]['api_key']);
537
538 // Restricted return -- because we don't have permission
539 $config->userPermissionClass->permissions = array('access CiviCRM', 'edit all contacts');
540 $result = $this->callAPISuccess('Contact', 'create', array(
541 'check_permissions' => 1,
542 'id' => $contactId,
543 'first_name' => 'A4',
544 ));
545 $this->assertEquals('A4', $result['values'][$contactId]['first_name']);
546 $this->assertEquals('B', $result['values'][$contactId]['last_name']);
547 $this->assertTrue(empty($result['values'][$contactId]['api_key']));
548 }
549
550 /**
551 * Check with complete array + custom field.
552 *
553 * Note that the test is written on purpose without any
554 * variables specific to participant so it can be replicated into other entities
555 * and / or moved to the automated test suite
556 */
557 public function testCreateWithCustom() {
558 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
559
560 $params = $this->_params;
561 $params['custom_' . $ids['custom_field_id']] = "custom string";
562 $description = "This demonstrates setting a custom field through the API.";
563 $result = $this->callAPIAndDocument($this->_entity, 'create', $params, __FUNCTION__, __FILE__, $description);
564
565 $check = $this->callAPISuccess($this->_entity, 'get', array(
566 'return.custom_' . $ids['custom_field_id'] => 1,
567 'id' => $result['id'],
568 ));
569 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
570
571 $this->customFieldDelete($ids['custom_field_id']);
572 $this->customGroupDelete($ids['custom_group_id']);
573 }
574
575 /**
576 * CRM-12773 - expectation is that civicrm quietly ignores fields without values.
577 */
578 public function testCreateWithNULLCustomCRM12773() {
579 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
580 $params = $this->_params;
581 $params['custom_' . $ids['custom_field_id']] = NULL;
582 $this->callAPISuccess('contact', 'create', $params);
583 $this->customFieldDelete($ids['custom_field_id']);
584 $this->customGroupDelete($ids['custom_group_id']);
585 }
586
587 /**
588 * CRM-14232 test preferred language set to site default if not passed.
589 */
590 public function testCreatePreferredLanguageUnset() {
591 $this->callAPISuccess('Contact', 'create', array(
592 'first_name' => 'Snoop',
593 'last_name' => 'Dog',
594 'contact_type' => 'Individual')
595 );
596 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
597 $this->assertEquals('en_US', $result['preferred_language']);
598 }
599
600 /**
601 * CRM-14232 test preferred language returns setting if not passed.
602 */
603 public function testCreatePreferredLanguageSet() {
604 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'fr_FR'));
605 $this->callAPISuccess('Contact', 'create', array(
606 'first_name' => 'Snoop',
607 'last_name' => 'Dog',
608 'contact_type' => 'Individual',
609 ));
610 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
611 $this->assertEquals('fr_FR', $result['preferred_language']);
612 }
613
614 /**
615 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
616 */
617 public function testCreatePreferredLanguageNull() {
618 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
619 $this->callAPISuccess('Contact', 'create', array(
620 'first_name' => 'Snoop',
621 'last_name' => 'Dog',
622 'contact_type' => 'Individual',
623 )
624 );
625 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
626 $this->assertEquals(NULL, $result['preferred_language']);
627 }
628
629 /**
630 * CRM-14232 test preferred language returns setting if not passed where setting is NULL.
631 */
632 public function testCreatePreferredLanguagePassed() {
633 $this->callAPISuccess('Setting', 'create', array('contact_default_language' => 'null'));
634 $this->callAPISuccess('Contact', 'create', array(
635 'first_name' => 'Snoop',
636 'last_name' => 'Dog',
637 'contact_type' => 'Individual',
638 'preferred_language' => 'en_AU',
639 ));
640 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Dog'));
641 $this->assertEquals('en_AU', $result['preferred_language']);
642 }
643
644 /**
645 * CRM-15792 - create/update datetime field for contact.
646 */
647 public function testCreateContactCustomFldDateTime() {
648 $customGroup = $this->customGroupCreate(array('extends' => 'Individual', 'title' => 'datetime_test_group'));
649 $dateTime = CRM_Utils_Date::currentDBDate();
650 //check date custom field is saved along with time when time_format is set
651 $params = array(
652 'first_name' => 'abc3',
653 'last_name' => 'xyz3',
654 'contact_type' => 'Individual',
655 'email' => 'man3@yahoo.com',
656 'api.CustomField.create' => array(
657 'custom_group_id' => $customGroup['id'],
658 'name' => 'test_datetime',
659 'label' => 'Demo Date',
660 'html_type' => 'Select Date',
661 'data_type' => 'Date',
662 'time_format' => 2,
663 'weight' => 4,
664 'is_required' => 1,
665 'is_searchable' => 0,
666 'is_active' => 1,
667 ),
668 );
669
670 $result = $this->callAPISuccess('Contact', 'create', $params);
671 $customFldId = $result['values'][$result['id']]['api.CustomField.create']['id'];
672 $this->assertNotNull($result['id']);
673 $this->assertNotNull($customFldId);
674
675 $params = array(
676 'id' => $result['id'],
677 "custom_{$customFldId}" => $dateTime,
678 'api.CustomValue.get' => 1,
679 );
680
681 $result = $this->callAPISuccess('Contact', 'create', $params);
682 $this->assertNotNull($result['id']);
683 $customFldDate = date("YmdHis", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
684 $this->assertNotNull($customFldDate);
685 $this->assertEquals($dateTime, $customFldDate);
686 $customValueId = $result['values'][$result['id']]['api.CustomValue.get']['values'][0]['id'];
687 $dateTime = date('Ymd');
688 //date custom field should not contain time part when time_format is null
689 $params = array(
690 'id' => $result['id'],
691 'api.CustomField.create' => array(
692 'id' => $customFldId,
693 'html_type' => 'Select Date',
694 'data_type' => 'Date',
695 'time_format' => '',
696 ),
697 'api.CustomValue.create' => array(
698 'id' => $customValueId,
699 'entity_id' => $result['id'],
700 "custom_{$customFldId}" => $dateTime,
701 ),
702 'api.CustomValue.get' => 1,
703 );
704 $result = $this->callAPISuccess('Contact', 'create', $params);
705 $this->assertNotNull($result['id']);
706 $customFldDate = date("Ymd", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
707 $customFldTime = date("His", strtotime($result['values'][$result['id']]['api.CustomValue.get']['values'][0]['latest']));
708 $this->assertNotNull($customFldDate);
709 $this->assertEquals($dateTime, $customFldDate);
710 $this->assertEquals(000000, $customFldTime);
711 $this->callAPISuccess('Contact', 'create', $params);
712 }
713
714
715 /**
716 * Test creating a current employer through API.
717 */
718 public function testContactCreateCurrentEmployer() {
719 // Here we will just do the get for set-up purposes.
720 $count = $this->callAPISuccess('contact', 'getcount', array(
721 'organization_name' => 'new employer org',
722 'contact_type' => 'Organization',
723 ));
724 $this->assertEquals(0, $count);
725 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
726 'current_employer' => 'new employer org',
727 )
728 ));
729 // do it again as an update to check it doesn't cause an error
730 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
731 'current_employer' => 'new employer org',
732 'id' => $employerResult['id'],
733 )
734 ));
735 $expectedCount = 1;
736 $this->callAPISuccess('contact', 'getcount', array(
737 'organization_name' => 'new employer org',
738 'contact_type' => 'Organization',
739 ),
740 $expectedCount);
741
742 $result = $this->callAPISuccess('contact', 'getsingle', array(
743 'id' => $employerResult['id'],
744 ));
745
746 $this->assertEquals('new employer org', $result['current_employer']);
747
748 }
749
750 /**
751 * Test creating a current employer through API.
752 *
753 * Check it will re-activate a de-activated employer
754 */
755 public function testContactCreateDuplicateCurrentEmployerEnables() {
756 // Set up - create employer relationship.
757 $employerResult = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
758 'current_employer' => 'new employer org',
759 )
760 ));
761 $relationship = $this->callAPISuccess('relationship', 'get', array(
762 'contact_id_a' => $employerResult['id'],
763 ));
764
765 //disable & check it is disabled
766 $this->callAPISuccess('relationship', 'create', array('id' => $relationship['id'], 'is_active' => 0));
767 $this->callAPISuccess('relationship', 'getvalue', array(
768 'id' => $relationship['id'],
769 'return' => 'is_active',
770 ), 0);
771
772 // Re-set the current employer - thus enabling the relationship.
773 $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
774 'current_employer' => 'new employer org',
775 'id' => $employerResult['id'],
776 )
777 ));
778 //check is_active is now 1
779 $relationship = $this->callAPISuccess('relationship', 'getsingle', array(
780 'return' => 'is_active',
781 ));
782 $this->assertEquals(1, $relationship['is_active']);
783 }
784
785 /**
786 * Check deceased contacts are not retrieved.
787 *
788 * Note at time of writing the default is to return default. This should possibly be changed & test added.
789 */
790 public function testGetDeceasedRetrieved() {
791 $this->callAPISuccess($this->_entity, 'create', $this->_params);
792 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
793 'first_name' => 'bb',
794 'last_name' => 'ccc',
795 'contact_type' => 'Individual',
796 'is_deceased' => 1,
797 ));
798 $result = $this->callAPISuccess($this->_entity, 'get', array('is_deceased' => 0));
799 $this->assertFalse(array_key_exists($c2['id'], $result['values']));
800 }
801
802 /**
803 * Test that sort works - old syntax.
804 */
805 public function testGetSort() {
806 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
807 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
808 'first_name' => 'bb',
809 'last_name' => 'ccc',
810 'contact_type' => 'Individual',
811 ));
812 $result = $this->callAPISuccess($this->_entity, 'get', array(
813 'sort' => 'first_name ASC',
814 'return.first_name' => 1,
815 'sequential' => 1,
816 'rowCount' => 1,
817 'contact_type' => 'Individual',
818 ));
819
820 $this->assertEquals('abc1', $result['values'][0]['first_name']);
821 $result = $this->callAPISuccess($this->_entity, 'get', array(
822 'sort' => 'first_name DESC',
823 'return.first_name' => 1,
824 'sequential' => 1,
825 'rowCount' => 1,
826 ));
827 $this->assertEquals('bb', $result['values'][0]['first_name']);
828
829 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
830 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
831 }
832
833 /**
834 * Test that we can retrieve contacts using array syntax.
835 *
836 * I.e 'id' => array('IN' => array('3,4')).
837 */
838 public function testGetINIDArray() {
839 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
840 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
841 'first_name' => 'bb',
842 'last_name' => 'ccc',
843 'contact_type' => 'Individual',
844 ));
845 $c3 = $this->callAPISuccess($this->_entity, 'create', array(
846 'first_name' => 'hh',
847 'last_name' => 'll',
848 'contact_type' => 'Individual',
849 ));
850 $result = $this->callAPISuccess($this->_entity, 'get', array('id' => array('IN' => array($c1['id'], $c3['id']))));
851 $this->assertEquals(2, $result['count']);
852 $this->assertEquals(array($c1['id'], $c3['id']), array_keys($result['values']));
853 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
854 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
855 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c3['id']));
856 }
857
858 /**
859 * Test variants on deleted behaviour.
860 */
861 public function testGetDeleted() {
862 $params = $this->_params;
863 $contact1 = $this->callAPISuccess('contact', 'create', $params);
864 $params['is_deleted'] = 1;
865 $params['last_name'] = 'bcd';
866 $contact2 = $this->callAPISuccess('contact', 'create', $params);
867 $countActive = $this->callAPISuccess('contact', 'getcount', array(
868 'showAll' => 'active',
869 'contact_type' => 'Individual',
870 ));
871 $countAll = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'all', 'contact_type' => 'Individual'));
872 $countTrash = $this->callAPISuccess('contact', 'getcount', array('showAll' => 'trash', 'contact_type' => 'Individual'));
873 $countDefault = $this->callAPISuccess('contact', 'getcount', array('contact_type' => 'Individual'));
874 $countDeleted = $this->callAPISuccess('contact', 'getcount', array(
875 'contact_type' => 'Individual',
876 'contact_is_deleted' => 1,
877 ));
878 $countNotDeleted = $this->callAPISuccess('contact', 'getcount', array(
879 'contact_is_deleted' => 0,
880 'contact_type' => 'Individual',
881 ));
882 $this->callAPISuccess('contact', 'delete', array('id' => $contact1['id']));
883 $this->callAPISuccess('contact', 'delete', array('id' => $contact2['id']));
884 $this->assertEquals(1, $countNotDeleted, 'contact_is_deleted => 0 is respected');
885 $this->assertEquals(1, $countActive);
886 $this->assertEquals(1, $countTrash);
887 $this->assertEquals(2, $countAll);
888 $this->assertEquals(1, $countDeleted);
889 $this->assertEquals(1, $countDefault, 'Only active by default in line');
890 }
891
892 /**
893 * Test that sort works - new syntax.
894 */
895 public function testGetSortNewSyntax() {
896 $c1 = $this->callAPISuccess($this->_entity, 'create', $this->_params);
897 $c2 = $this->callAPISuccess($this->_entity, 'create', array(
898 'first_name' => 'bb',
899 'last_name' => 'ccc',
900 'contact_type' => 'Individual',
901 ));
902 $result = $this->callAPISuccess($this->_entity, 'getvalue', array(
903 'return' => 'first_name',
904 'contact_type' => 'Individual',
905 'options' => array(
906 'limit' => 1,
907 'sort' => 'first_name',
908 ),
909 ));
910 $this->assertEquals('abc1', $result);
911
912 $result = $this->callAPISuccess($this->_entity, 'getvalue', array(
913 'return' => 'first_name',
914 'contact_type' => 'Individual',
915 'options' => array(
916 'limit' => 1,
917 'sort' => 'first_name DESC',
918 ),
919 ));
920 $this->assertEquals('bb', $result);
921
922 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c1['id']));
923 $this->callAPISuccess($this->_entity, 'delete', array('id' => $c2['id']));
924 }
925
926 /**
927 * Test sort and limit for chained relationship get.
928 *
929 * https://issues.civicrm.org/jira/browse/CRM-15983
930 */
931 public function testSortLimitChainedRelationshipGetCRM15983() {
932 // Some contact
933 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
934 'first_name' => 'Jules',
935 'last_name' => 'Smos',
936 'contact_type' => 'Individual',
937 ));
938
939 // Create another contact with two relationships.
940 $create_params = array(
941 'first_name' => 'Jos',
942 'last_name' => 'Smos',
943 'contact_type' => 'Individual',
944 'api.relationship.create' => array(
945 array(
946 'contact_id_a' => '$value.id',
947 'contact_id_b' => $create_result_1['id'],
948 // spouse of:
949 'relationship_type_id' => 2,
950 'start_date' => '2005-01-12',
951 'end_date' => '2006-01-11',
952 'description' => 'old',
953 ),
954 array(
955 'contact_id_a' => '$value.id',
956 'contact_id_b' => $create_result_1['id'],
957 // spouse of (was married twice :))
958 'relationship_type_id' => 2,
959 'start_date' => '2006-07-01',
960 'end_date' => '2010-07-01',
961 'description' => 'new',
962 ),
963 ),
964 );
965 $create_result = $this->callAPISuccess('contact', 'create', $create_params);
966
967 // Try to retrieve the contact and the most recent relationship.
968 $get_params = array(
969 'sequential' => 1,
970 'id' => $create_result['id'],
971 'api.relationship.get' => array(
972 'contact_id_a' => '$value.id',
973 'options' => array(
974 'limit' => '1',
975 'sort' => 'start_date DESC',
976 )),
977 );
978 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
979
980 // Clean up.
981 $this->callAPISuccess('contact', 'delete', array(
982 'id' => $create_result['id'],
983 ));
984
985 // Assert.
986 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
987 $this->assertEquals('new', $get_result['api.relationship.get']['values'][0]['description']);
988 }
989
990 /**
991 * Test apostrophe works in get & create.
992 */
993 public function testGetApostropheCRM10857() {
994 $params = array_merge($this->_params, array('last_name' => "O'Connor"));
995 $this->callAPISuccess($this->_entity, 'create', $params);
996 $result = $this->callAPISuccess($this->_entity, 'getsingle', array(
997 'last_name' => "O'Connor",
998 'sequential' => 1,
999 ));
1000 $this->assertEquals("O'Connor", $result['last_name'], 'in line' . __LINE__);
1001 }
1002
1003 /**
1004 * Test retrieval by addressee id.
1005 */
1006 public function testGetByAddresseeID() {
1007 $individual1ID = $this->individualCreate([
1008 'skip_greeting_processing' => 1,
1009 'addressee_id' => 'null',
1010 'email_greeting_id' => 'null',
1011 'postal_greeting_id' => 'null'
1012 ]);
1013 $individual2ID = $this->individualCreate();
1014
1015 $this->assertEquals($individual1ID,
1016 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'addressee_id' => ['IS NULL' => 1], 'return' => 'id'])
1017 );
1018 $this->assertEquals($individual1ID,
1019 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'email_greeting_id' => ['IS NULL' => 1], 'return' => 'id'])
1020 );
1021 $this->assertEquals($individual1ID,
1022 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'postal_greeting_id' => ['IS NULL' => 1], 'return' => 'id'])
1023 );
1024
1025 $this->assertEquals($individual2ID,
1026 $this->callAPISuccessGetValue('Contact', ['contact_type' => 'Individual', 'addressee_id' => ['NOT NULL' => 1], 'return' => 'id'])
1027 );
1028 }
1029
1030 /**
1031 * Check with complete array + custom field.
1032 *
1033 * Note that the test is written on purpose without any
1034 * variables specific to participant so it can be replicated into other entities
1035 * and / or moved to the automated test suite
1036 */
1037 public function testGetWithCustom() {
1038 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1039
1040 $params = $this->_params;
1041 $params['custom_' . $ids['custom_field_id']] = "custom string";
1042 $description = "This demonstrates setting a custom field through the API.";
1043 $subfile = "CustomFieldGet";
1044 $result = $this->callAPISuccess($this->_entity, 'create', $params);
1045
1046 $check = $this->callAPIAndDocument($this->_entity, 'get', array(
1047 'return.custom_' . $ids['custom_field_id'] => 1,
1048 'id' => $result['id'],
1049 ), __FUNCTION__, __FILE__, $description, $subfile);
1050
1051 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
1052 $fields = ($this->callAPISuccess('contact', 'getfields', $params));
1053 $this->assertTrue(is_array($fields['values']['custom_' . $ids['custom_field_id']]));
1054 $this->customFieldDelete($ids['custom_field_id']);
1055 $this->customGroupDelete($ids['custom_group_id']);
1056 }
1057
1058 /**
1059 * Check with complete array + custom field.
1060 *
1061 * Note that the test is written on purpose without any
1062 * variables specific to participant so it can be replicated into other entities
1063 * and / or moved to the automated test suite
1064 */
1065 public function testGetWithCustomReturnSyntax() {
1066 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
1067
1068 $params = $this->_params;
1069 $params['custom_' . $ids['custom_field_id']] = "custom string";
1070 $description = "This demonstrates setting a custom field through the API.";
1071 $subfile = "CustomFieldGetReturnSyntaxVariation";
1072 $result = $this->callAPISuccess($this->_entity, 'create', $params);
1073 $params = array('return' => 'custom_' . $ids['custom_field_id'], 'id' => $result['id']);
1074 $check = $this->callAPIAndDocument($this->_entity, 'get', $params, __FUNCTION__, __FILE__, $description, $subfile);
1075
1076 $this->assertEquals("custom string", $check['values'][$check['id']]['custom_' . $ids['custom_field_id']]);
1077 $this->customFieldDelete($ids['custom_field_id']);
1078 $this->customGroupDelete($ids['custom_group_id']);
1079 }
1080
1081 /**
1082 * Check that address name, ID is returned if required.
1083 */
1084 public function testGetReturnAddress() {
1085 $contactID = $this->individualCreate();
1086 $result = $this->callAPISuccess('address', 'create', array(
1087 'contact_id' => $contactID,
1088 'address_name' => 'My house',
1089 'location_type_id' => 'Home',
1090 'street_address' => '1 my road',
1091 ));
1092 $addressID = $result['id'];
1093
1094 $result = $this->callAPISuccessGetSingle('contact', array(
1095 'return' => 'address_name, street_address, address_id',
1096 'id' => $contactID,
1097 ));
1098 $this->assertEquals($addressID, $result['address_id']);
1099 $this->assertEquals('1 my road', $result['street_address']);
1100 $this->assertEquals('My house', $result['address_name']);
1101
1102 }
1103
1104 /**
1105 * Test group filter syntaxes.
1106 */
1107 public function testGetGroupIDFromContact() {
1108 $groupId = $this->groupCreate();
1109 $params = array(
1110 'email' => 'man2@yahoo.com',
1111 'contact_type' => 'Individual',
1112 'location_type_id' => 1,
1113 'api.group_contact.create' => array('group_id' => $groupId),
1114 );
1115
1116 $this->callAPISuccess('contact', 'create', $params);
1117 // testing as integer
1118 $params = array(
1119 'filter.group_id' => $groupId,
1120 'contact_type' => 'Individual',
1121 );
1122 $result = $this->callAPISuccess('contact', 'get', $params);
1123 $this->assertEquals(1, $result['count']);
1124 // group 26 doesn't exist, but we can still search contacts in it.
1125 $params = array(
1126 'filter.group_id' => 26,
1127 'contact_type' => 'Individual',
1128 );
1129 $this->callAPISuccess('contact', 'get', $params);
1130 // testing as string
1131 $params = array(
1132 'filter.group_id' => "$groupId, 26",
1133 'contact_type' => 'Individual',
1134 );
1135 $result = $this->callAPISuccess('contact', 'get', $params);
1136 $this->assertEquals(1, $result['count']);
1137 $params = array(
1138 'filter.group_id' => "26,27",
1139 'contact_type' => 'Individual',
1140 );
1141 $this->callAPISuccess('contact', 'get', $params);
1142
1143 // testing as string
1144 $params = array(
1145 'filter.group_id' => array($groupId, 26),
1146 'contact_type' => 'Individual',
1147 );
1148 $result = $this->callAPISuccess('contact', 'get', $params);
1149 $this->assertEquals(1, $result['count']);
1150
1151 //test in conjunction with other criteria
1152 $params = array(
1153 'filter.group_id' => array($groupId, 26),
1154 'contact_type' => 'Organization',
1155 );
1156 $this->callAPISuccess('contact', 'get', $params);
1157 $params = array(
1158 'filter.group_id' => array(26, 27),
1159 'contact_type' => 'Individual',
1160 );
1161 $result = $this->callAPISuccess('contact', 'get', $params);
1162 $this->assertEquals(0, $result['count']);
1163 }
1164
1165 /**
1166 * Verify that attempt to create individual contact with two chained websites succeeds.
1167 */
1168 public function testCreateIndividualWithContributionDottedSyntax() {
1169 $description = "This demonstrates the syntax to create 2 chained entities.";
1170 $subFile = "ChainTwoWebsites";
1171 $params = array(
1172 'first_name' => 'abc3',
1173 'last_name' => 'xyz3',
1174 'contact_type' => 'Individual',
1175 'email' => 'man3@yahoo.com',
1176 'api.contribution.create' => array(
1177 'receive_date' => '2010-01-01',
1178 'total_amount' => 100.00,
1179 'financial_type_id' => $this->_financialTypeId,
1180 'payment_instrument_id' => 1,
1181 'non_deductible_amount' => 10.00,
1182 'fee_amount' => 50.00,
1183 'net_amount' => 90.00,
1184 'trxn_id' => 15345,
1185 'invoice_id' => 67990,
1186 'source' => 'SSF',
1187 'contribution_status_id' => 1,
1188 ),
1189 'api.website.create' => array(
1190 'url' => "http://civicrm.org",
1191 ),
1192 'api.website.create.2' => array(
1193 'url' => "http://chained.org",
1194 ),
1195 );
1196
1197 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subFile);
1198
1199 // checking child function result not covered in callAPIAndDocument
1200 $this->assertAPISuccess($result['values'][$result['id']]['api.website.create']);
1201 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create.2']['values'][0]['url']);
1202 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create']['values'][0]['url']);
1203
1204 // delete the contact
1205 $this->callAPISuccess('contact', 'delete', $result);
1206 }
1207
1208 /**
1209 * Verify that attempt to create individual contact with chained contribution and website succeeds.
1210 */
1211 public function testCreateIndividualWithContributionChainedArrays() {
1212 $params = array(
1213 'first_name' => 'abc3',
1214 'last_name' => 'xyz3',
1215 'contact_type' => 'Individual',
1216 'email' => 'man3@yahoo.com',
1217 'api.contribution.create' => array(
1218 'receive_date' => '2010-01-01',
1219 'total_amount' => 100.00,
1220 'financial_type_id' => $this->_financialTypeId,
1221 'payment_instrument_id' => 1,
1222 'non_deductible_amount' => 10.00,
1223 'fee_amount' => 50.00,
1224 'net_amount' => 90.00,
1225 'trxn_id' => 12345,
1226 'invoice_id' => 67890,
1227 'source' => 'SSF',
1228 'contribution_status_id' => 1,
1229 ),
1230 'api.website.create' => array(
1231 array(
1232 'url' => "http://civicrm.org",
1233 ),
1234 array(
1235 'url' => "http://chained.org",
1236 'website_type_id' => 2,
1237 ),
1238 ),
1239 );
1240
1241 $description = "Demonstrates creating two websites as an array.";
1242 $subfile = "ChainTwoWebsitesSyntax2";
1243 $result = $this->callAPIAndDocument('Contact', 'create', $params, __FUNCTION__, __FILE__, $description, $subfile);
1244
1245 // the callAndDocument doesn't check the chained call
1246 $this->assertEquals(0, $result['values'][$result['id']]['api.website.create'][0]['is_error']);
1247 $this->assertEquals("http://chained.org", $result['values'][$result['id']]['api.website.create'][1]['values'][0]['url']);
1248 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.create'][0]['values'][0]['url']);
1249
1250 $this->callAPISuccess('contact', 'delete', $result);
1251 }
1252
1253 /**
1254 * Test for direction when chaining relationships.
1255 *
1256 * https://issues.civicrm.org/jira/browse/CRM-16084
1257 */
1258 public function testDirectionChainingRelationshipsCRM16084() {
1259 // Some contact, called Jules.
1260 $create_result_1 = $this->callAPISuccess('contact', 'create', array(
1261 'first_name' => 'Jules',
1262 'last_name' => 'Smos',
1263 'contact_type' => 'Individual',
1264 ));
1265
1266 // Another contact: Jos, child of Jules.
1267 $create_params = array(
1268 'first_name' => 'Jos',
1269 'last_name' => 'Smos',
1270 'contact_type' => 'Individual',
1271 'api.relationship.create' => array(
1272 array(
1273 'contact_id_a' => '$value.id',
1274 'contact_id_b' => $create_result_1['id'],
1275 // child of
1276 'relationship_type_id' => 1,
1277 ),
1278 ),
1279 );
1280 $create_result_2 = $this->callAPISuccess('contact', 'create', $create_params);
1281
1282 // Mia is the child of Jos.
1283 $create_params = array(
1284 'first_name' => 'Mia',
1285 'last_name' => 'Smos',
1286 'contact_type' => 'Individual',
1287 'api.relationship.create' => array(
1288 array(
1289 'contact_id_a' => '$value.id',
1290 'contact_id_b' => $create_result_2['id'],
1291 // child of
1292 'relationship_type_id' => 1,
1293 ),
1294 ),
1295 );
1296 $create_result_3 = $this->callAPISuccess('contact', 'create', $create_params);
1297
1298 // Get Jos and his children.
1299 $get_params = array(
1300 'sequential' => 1,
1301 'id' => $create_result_2['id'],
1302 'api.relationship.get' => array(
1303 'contact_id_b' => '$value.id',
1304 'relationship_type_id' => 1,
1305 ),
1306 );
1307 $get_result = $this->callAPISuccess('contact', 'getsingle', $get_params);
1308
1309 // Clean up first.
1310 $this->callAPISuccess('contact', 'delete', array(
1311 'id' => $create_result_1['id'],
1312 ));
1313 $this->callAPISuccess('contact', 'delete', array(
1314 'id' => $create_result_2['id'],
1315 ));
1316 $this->callAPISuccess('contact', 'delete', array(
1317 'id' => $create_result_2['id'],
1318 ));
1319
1320 // Assert.
1321 $this->assertEquals(1, $get_result['api.relationship.get']['count']);
1322 $this->assertEquals($create_result_3['id'], $get_result['api.relationship.get']['values'][0]['contact_id_a']);
1323 }
1324
1325 /**
1326 * Verify that attempt to create individual contact with first, and last names and email succeeds.
1327 */
1328 public function testCreateIndividualWithNameEmail() {
1329 $params = array(
1330 'first_name' => 'abc3',
1331 'last_name' => 'xyz3',
1332 'contact_type' => 'Individual',
1333 'email' => 'man3@yahoo.com',
1334 );
1335
1336 $contact = $this->callAPISuccess('contact', 'create', $params);
1337
1338 $this->callAPISuccess('contact', 'delete', $contact);
1339 }
1340
1341 /**
1342 * Verify that attempt to create individual contact with no data fails.
1343 */
1344 public function testCreateIndividualWithOutNameEmail() {
1345 $params = array(
1346 'contact_type' => 'Individual',
1347 );
1348 $this->callAPIFailure('contact', 'create', $params);
1349 }
1350
1351 /**
1352 * Test create individual contact with first &last names, email and location type succeeds.
1353 */
1354 public function testCreateIndividualWithNameEmailLocationType() {
1355 $params = array(
1356 'first_name' => 'abc4',
1357 'last_name' => 'xyz4',
1358 'email' => 'man4@yahoo.com',
1359 'contact_type' => 'Individual',
1360 'location_type_id' => 1,
1361 );
1362 $result = $this->callAPISuccess('contact', 'create', $params);
1363
1364 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
1365 }
1366
1367 /**
1368 * Verify that when changing employers the old employer relationship becomes inactive.
1369 */
1370 public function testCreateIndividualWithEmployer() {
1371 $employer = $this->organizationCreate();
1372 $employer2 = $this->organizationCreate();
1373
1374 $params = array(
1375 'email' => 'man4@yahoo.com',
1376 'contact_type' => 'Individual',
1377 'employer_id' => $employer,
1378 );
1379
1380 $result = $this->callAPISuccess('contact', 'create', $params);
1381 $relationships = $this->callAPISuccess('relationship', 'get', array(
1382 'contact_id_a' => $result['id'],
1383 'sequential' => 1,
1384 ));
1385
1386 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1387
1388 // Add more random relationships to make the test more realistic
1389 foreach (array('Employee of', 'Volunteer for') as $relationshipType) {
1390 $relTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', $relationshipType, 'id', 'name_a_b');
1391 $this->callAPISuccess('relationship', 'create', array(
1392 'contact_id_a' => $result['id'],
1393 'contact_id_b' => $this->organizationCreate(),
1394 'is_active' => 1,
1395 'relationship_type_id' => $relTypeId,
1396 ));
1397 }
1398
1399 // Add second employer
1400 $params['employer_id'] = $employer2;
1401 $params['id'] = $result['id'];
1402 $result = $this->callAPISuccess('contact', 'create', $params);
1403
1404 $relationships = $this->callAPISuccess('relationship', 'get', array(
1405 'contact_id_a' => $result['id'],
1406 'sequential' => 1,
1407 'is_active' => 0,
1408 ));
1409
1410 $this->assertEquals($employer, $relationships['values'][0]['contact_id_b']);
1411 }
1412
1413 /**
1414 * Verify that attempt to create household contact with details succeeds.
1415 */
1416 public function testCreateHouseholdDetails() {
1417 $params = array(
1418 'household_name' => 'abc8\'s House',
1419 'nick_name' => 'x House',
1420 'email' => 'man8@yahoo.com',
1421 'contact_type' => 'Household',
1422 );
1423
1424 $contact = $this->callAPISuccess('contact', 'create', $params);
1425
1426 $this->callAPISuccess('contact', 'delete', $contact);
1427 }
1428
1429 /**
1430 * Verify that attempt to create household contact with inadequate details fails.
1431 */
1432 public function testCreateHouseholdInadequateDetails() {
1433 $params = array(
1434 'nick_name' => 'x House',
1435 'email' => 'man8@yahoo.com',
1436 'contact_type' => 'Household',
1437 );
1438 $this->callAPIFailure('contact', 'create', $params);
1439 }
1440
1441 /**
1442 * Verify successful update of individual contact.
1443 */
1444 public function testUpdateIndividualWithAll() {
1445 // Insert a row in civicrm_contact creating individual contact.
1446 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1447 $op->execute($this->_dbconn,
1448 $this->createXMLDataSet(
1449 dirname(__FILE__) . '/dataset/contact_ind.xml'
1450 )
1451 );
1452
1453 $params = array(
1454 'id' => 23,
1455 'first_name' => 'abcd',
1456 'contact_type' => 'Individual',
1457 'nick_name' => 'This is nickname first',
1458 'do_not_email' => '1',
1459 'do_not_phone' => '1',
1460 'do_not_mail' => '1',
1461 'do_not_trade' => '1',
1462 'legal_identifier' => 'ABC23853ZZ2235',
1463 'external_identifier' => '1928837465',
1464 'image_URL' => 'http://some.url.com/image.jpg',
1465 'home_url' => 'http://www.example.org',
1466
1467 );
1468
1469 $this->callAPISuccess('Contact', 'Update', $params);
1470 $getResult = $this->callAPISuccess('Contact', 'Get', $params);
1471 unset($params['contact_id']);
1472 //Todo - neither API v2 or V3 are testing for home_url - not sure if it is being set.
1473 //reducing this test partially back to api v2 level to get it through
1474 unset($params['home_url']);
1475 foreach ($params as $key => $value) {
1476 $this->assertEquals($value, $getResult['values'][23][$key]);
1477 }
1478 // Check updated civicrm_contact against expected.
1479 $expected = $this->createXMLDataSet(
1480 dirname(__FILE__) . '/dataset/contact_ind_upd.xml'
1481 );
1482 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1483 $this->_dbconn
1484 );
1485 $actual->addTable('civicrm_contact');
1486 $expected->matches($actual);
1487 }
1488
1489 /**
1490 * Verify successful update of organization contact.
1491 */
1492 public function testUpdateOrganizationWithAll() {
1493 // Insert a row in civicrm_contact creating organization contact
1494 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1495 $op->execute($this->_dbconn,
1496 $this->createXMLDataSet(
1497 dirname(__FILE__) . '/dataset/contact_org.xml'
1498 )
1499 );
1500
1501 $params = array(
1502 'id' => 24,
1503 'organization_name' => 'WebAccess India Pvt Ltd',
1504 'legal_name' => 'WebAccess',
1505 'sic_code' => 'ABC12DEF',
1506 'contact_type' => 'Organization',
1507 );
1508
1509 $this->callAPISuccess('Contact', 'Update', $params);
1510
1511 // Check updated civicrm_contact against expected.
1512 $expected = $this->createXMLDataSet(
1513 dirname(__FILE__) . '/dataset/contact_org_upd.xml'
1514 );
1515 $actual = new PHPUnit_Extensions_Database_DataSet_QueryDataSet(
1516 $this->_dbconn
1517 );
1518 $actual->addTable('civicrm_contact');
1519 $expected->matches($actual);
1520 }
1521
1522 /**
1523 * Test merging 2 organizations.
1524 *
1525 * CRM-20421: This test make sure that inherited memberships are deleted upon merging organization.
1526 */
1527 public function testMergeOrganizations() {
1528 $organizationID1 = $this->organizationCreate(array(), 0);
1529 $organizationID2 = $this->organizationCreate(array(), 1);
1530 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
1531 'employer_id' => $organizationID1,
1532 )
1533 ));
1534 $contact = $contact["values"][$contact["id"]];
1535
1536 $membershipType = $this->createEmployerOfMembership();
1537 $membershipParams = array(
1538 'membership_type_id' => $membershipType["id"],
1539 'contact_id' => $organizationID1,
1540 'start_date' => "01/01/2015",
1541 'join_date' => "01/01/2010",
1542 'end_date' => "12/31/2015",
1543 );
1544 $ownermembershipid = $this->contactMembershipCreate($membershipParams);
1545
1546 $contactmembership = $this->callAPISuccess("membership", "getsingle", array(
1547 "contact_id" => $contact["id"],
1548 ));
1549
1550 $this->assertEquals($ownermembershipid, $contactmembership["owner_membership_id"], "Contact membership must be inherited from Organization");
1551
1552 CRM_Dedupe_Merger::moveAllBelongings($organizationID2, $organizationID1, array(
1553 "move_rel_table_memberships" => "0",
1554 "move_rel_table_relationships" => "1",
1555 "main_details" => array(
1556 "contact_id" => $organizationID2,
1557 "contact_type" => "Organization",
1558 ),
1559 "other_details" => array(
1560 "contact_id" => $organizationID1,
1561 "contact_type" => "Organization",
1562 ),
1563 ));
1564
1565 $contactmembership = $this->callAPISuccess("membership", "get", array(
1566 "contact_id" => $contact["id"],
1567 ));
1568
1569 $this->assertEquals(0, $contactmembership["count"], "Contact membership must be deleted after merging organization without memberships.");
1570 }
1571
1572 private function createEmployerOfMembership() {
1573 $params = array(
1574 'domain_id' => CRM_Core_Config::domainID(),
1575 'name' => 'Organization Membership',
1576 'description' => NULL,
1577 'member_of_contact_id' => 1,
1578 'financial_type_id' => 1,
1579 'minimum_fee' => 10,
1580 'duration_unit' => 'year',
1581 'duration_interval' => 1,
1582 'period_type' => 'rolling',
1583 'relationship_type_id' => 5,
1584 'relationship_direction' => 'b_a',
1585 'visibility' => 'Public',
1586 'is_active' => 1,
1587 );
1588 $membershipType = $this->callAPISuccess('membership_type', 'create', $params);
1589 return $membershipType["values"][$membershipType["id"]];
1590 }
1591
1592 /**
1593 * Verify successful update of household contact.
1594 */
1595 public function testUpdateHouseholdWithAll() {
1596 // Insert a row in civicrm_contact creating household contact
1597 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1598 $op->execute($this->_dbconn,
1599 $this->createXMLDataSet(
1600 dirname(__FILE__) . '/dataset/contact_hld.xml'
1601 )
1602 );
1603
1604 $params = array(
1605 'id' => 25,
1606 'household_name' => 'ABC household',
1607 'nick_name' => 'ABC House',
1608 'contact_type' => 'Household',
1609 );
1610
1611 $result = $this->callAPISuccess('Contact', 'Update', $params);
1612
1613 $expected = array(
1614 'contact_type' => 'Household',
1615 'is_opt_out' => 0,
1616 'sort_name' => 'ABC household',
1617 'display_name' => 'ABC household',
1618 'nick_name' => 'ABC House',
1619 );
1620 $this->getAndCheck($expected, $result['id'], 'contact');
1621 }
1622
1623 /**
1624 * Test civicrm_update() without contact type.
1625 *
1626 * Deliberately exclude contact_type as it should still cope using civicrm_api.
1627 *
1628 * CRM-7645.
1629 */
1630 public function testUpdateCreateWithID() {
1631 // Insert a row in civicrm_contact creating individual contact.
1632 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1633 $op->execute($this->_dbconn,
1634 $this->createXMLDataSet(
1635 dirname(__FILE__) . '/dataset/contact_ind.xml'
1636 )
1637 );
1638
1639 $params = array(
1640 'id' => 23,
1641 'first_name' => 'abcd',
1642 'last_name' => 'wxyz',
1643 );
1644 $this->callAPISuccess('Contact', 'Update', $params);
1645 }
1646
1647 /**
1648 * Test civicrm_contact_delete() with no contact ID.
1649 */
1650 public function testContactDeleteNoID() {
1651 $params = array(
1652 'foo' => 'bar',
1653 );
1654 $this->callAPIFailure('contact', 'delete', $params);
1655 }
1656
1657 /**
1658 * Test civicrm_contact_delete() with error.
1659 */
1660 public function testContactDeleteError() {
1661 $params = array('contact_id' => 999);
1662 $this->callAPIFailure('contact', 'delete', $params);
1663 }
1664
1665 /**
1666 * Test civicrm_contact_delete().
1667 */
1668 public function testContactDelete() {
1669 $contactID = $this->individualCreate();
1670 $params = array(
1671 'id' => $contactID,
1672 );
1673 $this->callAPIAndDocument('contact', 'delete', $params, __FUNCTION__, __FILE__);
1674 }
1675
1676 /**
1677 * Test civicrm_contact_get() return only first name.
1678 */
1679 public function testContactGetRetFirst() {
1680 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1681 $params = array(
1682 'contact_id' => $contact['id'],
1683 'return_first_name' => TRUE,
1684 'sort' => 'first_name',
1685 );
1686 $result = $this->callAPISuccess('contact', 'get', $params);
1687 $this->assertEquals(1, $result['count']);
1688 $this->assertEquals($contact['id'], $result['id']);
1689 $this->assertEquals('abc1', $result['values'][$contact['id']]['first_name']);
1690 }
1691
1692 /**
1693 * Test civicrm_contact_get() return only first name & last name.
1694 *
1695 * Use comma separated string return with a space.
1696 */
1697 public function testContactGetReturnFirstLast() {
1698 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1699 $params = array(
1700 'contact_id' => $contact['id'],
1701 'return' => 'first_name, last_name',
1702 );
1703 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1704 $this->assertEquals('abc1', $result['first_name']);
1705 $this->assertEquals('xyz1', $result['last_name']);
1706 //check that other defaults not returns
1707 $this->assertArrayNotHasKey('sort_name', $result);
1708 $params = array(
1709 'contact_id' => $contact['id'],
1710 'return' => 'first_name,last_name',
1711 );
1712 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1713 $this->assertEquals('abc1', $result['first_name']);
1714 $this->assertEquals('xyz1', $result['last_name']);
1715 //check that other defaults not returns
1716 $this->assertArrayNotHasKey('sort_name', $result);
1717 }
1718
1719 /**
1720 * Test civicrm_contact_get() return only first name & last name.
1721 *
1722 * Use comma separated string return without a space
1723 */
1724 public function testContactGetReturnFirstLastNoComma() {
1725 $contact = $this->callAPISuccess('contact', 'create', $this->_params);
1726 $params = array(
1727 'contact_id' => $contact['id'],
1728 'return' => 'first_name,last_name',
1729 );
1730 $result = $this->callAPISuccess('contact', 'getsingle', $params);
1731 $this->assertEquals('abc1', $result['first_name']);
1732 $this->assertEquals('xyz1', $result['last_name']);
1733 //check that other defaults not returns
1734 $this->assertArrayNotHasKey('sort_name', $result);
1735 }
1736
1737 /**
1738 * Test civicrm_contact_get() with default return properties.
1739 */
1740 public function testContactGetRetDefault() {
1741 $contactID = $this->individualCreate();
1742 $params = array(
1743 'contact_id' => $contactID,
1744 'sort' => 'first_name',
1745 );
1746 $result = $this->callAPISuccess('contact', 'get', $params);
1747 $this->assertEquals($contactID, $result['values'][$contactID]['contact_id']);
1748 $this->assertEquals('Anthony', $result['values'][$contactID]['first_name']);
1749 }
1750
1751 /**
1752 * Test civicrm_contact_getquick() with empty name param.
1753 */
1754 public function testContactGetQuick() {
1755 // Insert a row in civicrm_contact creating individual contact.
1756 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1757 $op->execute($this->_dbconn,
1758 $this->createXMLDataSet(
1759 dirname(__FILE__) . '/dataset/contact_17.xml'
1760 )
1761 );
1762 $op->execute($this->_dbconn,
1763 $this->createXMLDataSet(
1764 dirname(__FILE__) . '/dataset/email_contact_17.xml'
1765 )
1766 );
1767 $params = array(
1768 'name' => "T",
1769 );
1770
1771 $result = $this->callAPISuccess('contact', 'getquick', $params);
1772 $this->assertEquals(17, $result['values'][0]['id']);
1773 }
1774
1775 /**
1776 * Test civicrm_contact_get) with empty params.
1777 */
1778 public function testContactGetEmptyParams() {
1779 $this->callAPISuccess('contact', 'get', array());
1780 }
1781
1782 /**
1783 * Test civicrm_contact_get(,true) with no matches.
1784 */
1785 public function testContactGetOldParamsNoMatches() {
1786 // Insert a row in civicrm_contact creating contact 17.
1787 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1788 $op->execute($this->_dbconn,
1789 $this->createXMLDataSet(
1790 dirname(__FILE__) . '/dataset/contact_17.xml'
1791 )
1792 );
1793
1794 $params = array(
1795 'first_name' => 'Fred',
1796 );
1797 $result = $this->callAPISuccess('contact', 'get', $params);
1798 $this->assertEquals(0, $result['count']);
1799 }
1800
1801 /**
1802 * Test civicrm_contact_get(,true) with one match.
1803 */
1804 public function testContactGetOldParamsOneMatch() {
1805 // Insert a row in civicrm_contact creating contact 17
1806 $op = new PHPUnit_Extensions_Database_Operation_Insert();
1807 $op->execute($this->_dbconn,
1808 $this->createXMLDataSet(dirname(__FILE__) . '/dataset/contact_17.xml'
1809 )
1810 );
1811
1812 $params = array(
1813 'first_name' => 'Test',
1814 );
1815 $result = $this->callAPISuccess('contact', 'get', $params);
1816 $this->assertEquals(17, $result['values'][17]['contact_id']);
1817 $this->assertEquals(17, $result['id']);
1818 }
1819
1820 /**
1821 * Test civicrm_contact_search_count().
1822 */
1823 public function testContactGetEmail() {
1824 $params = array(
1825 'email' => 'man2@yahoo.com',
1826 'contact_type' => 'Individual',
1827 'location_type_id' => 1,
1828 );
1829
1830 $contact = $this->callAPISuccess('contact', 'create', $params);
1831
1832 $params = array(
1833 'email' => 'man2@yahoo.com',
1834 );
1835 $result = $this->callAPIAndDocument('contact', 'get', $params, __FUNCTION__, __FILE__);
1836 $this->assertEquals('man2@yahoo.com', $result['values'][$result['id']]['email']);
1837
1838 $this->callAPISuccess('contact', 'delete', $contact);
1839 }
1840
1841 /**
1842 * Ensure consistent return format for option group fields.
1843 */
1844 public function testSetPreferredCommunicationNull() {
1845 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
1846 'preferred_communication_method' => array('Phone', 'SMS'),
1847 )));
1848 $preferredCommunicationMethod = $this->callAPISuccessGetValue('Contact', array(
1849 'id' => $contact['id'],
1850 'return' => 'preferred_communication_method',
1851 ));
1852 $this->assertNotEmpty($preferredCommunicationMethod);
1853 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array(
1854 'preferred_communication_method' => 'null',
1855 'id' => $contact['id'],
1856 )));
1857 $preferredCommunicationMethod = $this->callAPISuccessGetValue('Contact', array(
1858 'id' => $contact['id'],
1859 'return' => 'preferred_communication_method',
1860 ));
1861 $this->assertEmpty($preferredCommunicationMethod);
1862 }
1863
1864 /**
1865 * Ensure consistent return format for option group fields.
1866 */
1867 public function testPseudoFields() {
1868 $params = array(
1869 'preferred_communication_method' => array('Phone', 'SMS'),
1870 'preferred_language' => 'en_US',
1871 'gender_id' => 'Female',
1872 'prefix_id' => 'Mrs.',
1873 'suffix_id' => 'II',
1874 'communication_style_id' => 'Formal',
1875 );
1876
1877 $contact = $this->callAPISuccess('contact', 'create', array_merge($this->_params, $params));
1878
1879 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contact['id']));
1880 $this->assertEquals('Both', $result['preferred_mail_format']);
1881
1882 $this->assertEquals('en_US', $result['preferred_language']);
1883 $this->assertEquals(1, $result['communication_style_id']);
1884 $this->assertEquals(1, $result['gender_id']);
1885 $this->assertEquals('Female', $result['gender']);
1886 $this->assertEquals('Mrs.', $result['individual_prefix']);
1887 $this->assertEquals(1, $result['prefix_id']);
1888 $this->assertEquals('II', $result['individual_suffix']);
1889 $this->assertEquals(CRM_Core_PseudoConstant::getKey("CRM_Contact_BAO_Contact", 'suffix_id', 'II'), $result['suffix_id']);
1890 $this->callAPISuccess('contact', 'delete', $contact);
1891 $this->assertEquals(array(
1892 CRM_Core_PseudoConstant::getKey("CRM_Contact_BAO_Contact", 'preferred_communication_method', 'Phone'),
1893 CRM_Core_PseudoConstant::getKey("CRM_Contact_BAO_Contact", 'preferred_communication_method', 'SMS'),
1894 ), $result['preferred_communication_method']);
1895 }
1896
1897
1898 /**
1899 * Test birth date parameters.
1900 *
1901 * These include value, array & birth_date_high, birth_date_low
1902 * && deceased.
1903 */
1904 public function testContactGetBirthDate() {
1905 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('birth_date' => 'first day of next month - 2 years')));
1906 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('birth_date' => 'first day of next month - 5 years')));
1907 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('birth_date' => 'first day of next month -20 years')));
1908
1909 $result = $this->callAPISuccess('contact', 'get', array());
1910 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['birth_date']);
1911 $result = $this->callAPISuccess('contact', 'get', array('birth_date' => 'first day of next month -5 years'));
1912 $this->assertEquals(1, $result['count']);
1913 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1914 $result = $this->callAPISuccess('contact', 'get', array('birth_date_high' => date('Y-m-d', strtotime('-6 years'))));
1915 $this->assertEquals(1, $result['count']);
1916 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['birth_date']);
1917 $result = $this->callAPISuccess('contact', 'get', array(
1918 'birth_date_low' => date('Y-m-d', strtotime('-6 years')),
1919 'birth_date_high' => date('Y-m-d', strtotime('- 3 years')),
1920 ));
1921 $this->assertEquals(1, $result['count']);
1922 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1923 $result = $this->callAPISuccess('contact', 'get', array(
1924 'birth_date_low' => '-6 years',
1925 'birth_date_high' => '- 3 years',
1926 ));
1927 $this->assertEquals(1, $result['count']);
1928 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['birth_date']);
1929 }
1930
1931 /**
1932 * Test Address parameters
1933 *
1934 * This include state_province, state_province_name, country
1935 */
1936 public function testContactGetWithAddressFields() {
1937 $individuals = array(
1938 array(
1939 'first_name' => 'abc1',
1940 'contact_type' => 'Individual',
1941 'last_name' => 'xyz1',
1942 'api.address.create' => array(
1943 'country' => 'United States',
1944 'state_province_id' => 'Michigan',
1945 'location_type_id' => 1,
1946 ),
1947 ),
1948 array(
1949 'first_name' => 'abc2',
1950 'contact_type' => 'Individual',
1951 'last_name' => 'xyz2',
1952 'api.address.create' => array(
1953 'country' => 'United States',
1954 'state_province_id' => 'Alabama',
1955 'location_type_id' => 1,
1956 ),
1957 ),
1958 );
1959 foreach ($individuals as $params) {
1960 $contact = $this->callAPISuccess('contact', 'create', $params);
1961 }
1962
1963 // Check whether Contact get API return successfully with below Address params.
1964 $fieldsToTest = array(
1965 'state_province_name' => 'Michigan',
1966 'state_province' => 'Michigan',
1967 'country' => 'United States',
1968 'state_province_name' => array('IN' => array('Michigan', 'Alabama')),
1969 'state_province' => array('IN' => array('Michigan', 'Alabama')),
1970 );
1971 foreach ($fieldsToTest as $field => $value) {
1972 $getParams = array(
1973 'id' => $contact['id'],
1974 $field => $value,
1975 );
1976 $result = $this->callAPISuccess('Contact', 'get', $getParams);
1977 $this->assertEquals(1, $result['count']);
1978 }
1979 }
1980
1981 /**
1982 * Test Deceased date parameters.
1983 *
1984 * These include value, array & Deceased_date_high, Deceased date_low
1985 * && deceased.
1986 */
1987 public function testContactGetDeceasedDate() {
1988 $contact1 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('deceased_date' => 'first day of next month - 2 years')));
1989 $contact2 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('deceased_date' => 'first day of next month - 5 years')));
1990 $contact3 = $this->callAPISuccess('contact', 'create', array_merge($this->_params, array('deceased_date' => 'first day of next month -20 years')));
1991
1992 $result = $this->callAPISuccess('contact', 'get', array());
1993 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -2 years')), $result['values'][$contact1['id']]['deceased_date']);
1994 $result = $this->callAPISuccess('contact', 'get', array('deceased_date' => 'first day of next month -5 years'));
1995 $this->assertEquals(1, $result['count']);
1996 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
1997 $result = $this->callAPISuccess('contact', 'get', array('deceased_date_high' => date('Y-m-d', strtotime('-6 years'))));
1998 $this->assertEquals(1, $result['count']);
1999 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -20 years')), $result['values'][$contact3['id']]['deceased_date']);
2000 $result = $this->callAPISuccess('contact', 'get', array(
2001 'deceased_date_low' => '-6 years',
2002 'deceased_date_high' => date('Y-m-d', strtotime('- 3 years')),
2003 ));
2004 $this->assertEquals(1, $result['count']);
2005 $this->assertEquals(date('Y-m-d', strtotime('first day of next month -5 years')), $result['values'][$contact2['id']]['deceased_date']);
2006 }
2007
2008 /**
2009 * Test for Contact.get id=@user:username.
2010 */
2011 public function testContactGetByUsername() {
2012 // Setup - create contact with a uf-match.
2013 $cid = $this->individualCreate(array(
2014 'contact_type' => 'Individual',
2015 'first_name' => 'testGetByUsername',
2016 'last_name' => 'testGetByUsername',
2017 ));
2018
2019 $ufMatchParams = array(
2020 'domain_id' => CRM_Core_Config::domainID(),
2021 'uf_id' => 99,
2022 'uf_name' => 'the-email-matching-key-is-not-really-the-username',
2023 'contact_id' => $cid,
2024 );
2025 $ufMatch = CRM_Core_BAO_UFMatch::create($ufMatchParams);
2026 $this->assertTrue(is_numeric($ufMatch->id));
2027
2028 // setup - mock the calls to CRM_Utils_System_*::getUfId
2029 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
2030 $userSystem->expects($this->once())
2031 ->method('getUfId')
2032 ->with($this->equalTo('exampleUser'))
2033 ->will($this->returnValue(99));
2034 CRM_Core_Config::singleton()->userSystem = $userSystem;
2035
2036 // perform a lookup
2037 $result = $this->callAPISuccess('Contact', 'get', array(
2038 'id' => '@user:exampleUser',
2039 ));
2040 $this->assertEquals('testGetByUsername', $result['values'][$cid]['first_name']);
2041 }
2042
2043 /**
2044 * Test to check return works OK.
2045 */
2046 public function testContactGetReturnValues() {
2047 $extraParams = array(
2048 'nick_name' => 'Bob',
2049 'phone' => '456',
2050 'email' => 'e@mail.com',
2051 );
2052 $contactID = $this->individualCreate($extraParams);
2053 //actually it turns out the above doesn't create a phone
2054 $this->callAPISuccess('phone', 'create', array('contact_id' => $contactID, 'phone' => '456'));
2055 $result = $this->callAPISuccess('contact', 'getsingle', array('id' => $contactID));
2056 foreach ($extraParams as $key => $value) {
2057 $this->assertEquals($result[$key], $value);
2058 }
2059 //now we check they are still returned with 'return' key
2060 $result = $this->callAPISuccess('contact', 'getsingle', array(
2061 'id' => $contactID,
2062 'return' => array_keys($extraParams),
2063 ));
2064 foreach ($extraParams as $key => $value) {
2065 $this->assertEquals($result[$key], $value);
2066 }
2067 }
2068
2069 /**
2070 * Test creating multiple phones using chaining.
2071 *
2072 * @throws \Exception
2073 */
2074 public function testCRM13252MultipleChainedPhones() {
2075 $contactID = $this->householdCreate();
2076 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 0);
2077 $params = array(
2078 'contact_id' => $contactID,
2079 'household_name' => 'Household 1',
2080 'contact_type' => 'Household',
2081 'api.phone.create' => array(
2082 0 => array(
2083 'phone' => '111-111-1111',
2084 'location_type_id' => 1,
2085 'phone_type_id' => 1,
2086 ),
2087 1 => array(
2088 'phone' => '222-222-2222',
2089 'location_type_id' => 1,
2090 'phone_type_id' => 2,
2091 ),
2092 ),
2093 );
2094 $this->callAPISuccess('contact', 'create', $params);
2095 $this->callAPISuccessGetCount('phone', array('contact_id' => $contactID), 2);
2096
2097 }
2098
2099 /**
2100 * Test for Contact.get id=@user:username (with an invalid username).
2101 */
2102 public function testContactGetByUnknownUsername() {
2103 // setup - mock the calls to CRM_Utils_System_*::getUfId
2104 $userSystem = $this->getMock('CRM_Utils_System_UnitTests', array('getUfId'));
2105 $userSystem->expects($this->once())
2106 ->method('getUfId')
2107 ->with($this->equalTo('exampleUser'))
2108 ->will($this->returnValue(NULL));
2109 CRM_Core_Config::singleton()->userSystem = $userSystem;
2110
2111 // perform a lookup
2112 $result = $this->callAPIFailure('Contact', 'get', array(
2113 'id' => '@user:exampleUser',
2114 ));
2115 $this->assertRegExp('/cannot be resolved to a contact ID/', $result['error_message']);
2116 }
2117
2118 /**
2119 * Verify attempt to create individual with chained arrays and sequential.
2120 */
2121 public function testGetIndividualWithChainedArraysAndSequential() {
2122 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
2123 $params['custom_' . $ids['custom_field_id']] = "custom string";
2124
2125 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2126 $params = array(
2127 'sequential' => 1,
2128 'first_name' => 'abc3',
2129 'last_name' => 'xyz3',
2130 'contact_type' => 'Individual',
2131 'email' => 'man3@yahoo.com',
2132 'api.website.create' => array(
2133 array(
2134 'url' => "http://civicrm.org",
2135 ),
2136 array(
2137 'url' => "https://civicrm.org",
2138 ),
2139 ),
2140 );
2141
2142 $result = $this->callAPISuccess('Contact', 'create', $params);
2143
2144 // delete the contact and custom groups
2145 $this->callAPISuccess('contact', 'delete', array('id' => $result['id']));
2146 $this->customGroupDelete($ids['custom_group_id']);
2147 $this->customGroupDelete($moreIDs['custom_group_id']);
2148
2149 $this->assertEquals($result['id'], $result['values'][0]['id']);
2150 $this->assertArrayKeyExists('api.website.create', $result['values'][0]);
2151 }
2152
2153 /**
2154 * Verify attempt to create individual with chained arrays.
2155 */
2156 public function testGetIndividualWithChainedArrays() {
2157 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
2158 $params['custom_' . $ids['custom_field_id']] = "custom string";
2159
2160 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2161 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
2162 $subfile = "APIChainedArray";
2163 $params = array(
2164 'first_name' => 'abc3',
2165 'last_name' => 'xyz3',
2166 'contact_type' => 'Individual',
2167 'email' => 'man3@yahoo.com',
2168 'api.contribution.create' => array(
2169 'receive_date' => '2010-01-01',
2170 'total_amount' => 100.00,
2171 'financial_type_id' => 1,
2172 'payment_instrument_id' => 1,
2173 'non_deductible_amount' => 10.00,
2174 'fee_amount' => 50.00,
2175 'net_amount' => 90.00,
2176 'trxn_id' => 12345,
2177 'invoice_id' => 67890,
2178 'source' => 'SSF',
2179 'contribution_status_id' => 1,
2180 ),
2181 'api.contribution.create.1' => array(
2182 'receive_date' => '2011-01-01',
2183 'total_amount' => 120.00,
2184 'financial_type_id' => $this->_financialTypeId = 1,
2185 'payment_instrument_id' => 1,
2186 'non_deductible_amount' => 10.00,
2187 'fee_amount' => 50.00,
2188 'net_amount' => 90.00,
2189 'trxn_id' => 12335,
2190 'invoice_id' => 67830,
2191 'source' => 'SSF',
2192 'contribution_status_id' => 1,
2193 ),
2194 'api.website.create' => array(
2195 array(
2196 'url' => "http://civicrm.org",
2197 ),
2198 ),
2199 );
2200
2201 $result = $this->callAPISuccess('Contact', 'create', $params);
2202 $params = array(
2203 'id' => $result['id'],
2204 'api.website.get' => array(),
2205 'api.Contribution.get' => array(
2206 'total_amount' => '120.00',
2207 ),
2208 'api.CustomValue.get' => 1,
2209 'api.Note.get' => 1,
2210 );
2211 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
2212 // delete the contact
2213 $this->callAPISuccess('contact', 'delete', $result);
2214 $this->customGroupDelete($ids['custom_group_id']);
2215 $this->customGroupDelete($moreIDs['custom_group_id']);
2216 $this->assertEquals(0, $result['values'][$result['id']]['api.website.get']['is_error']);
2217 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.get']['values'][0]['url']);
2218 }
2219
2220 /**
2221 * Verify attempt to create individual with chained arrays and sequential.
2222 *
2223 * See https://issues.civicrm.org/jira/browse/CRM-15815
2224 */
2225 public function testCreateIndividualWithChainedArrayAndSequential() {
2226 $params = array(
2227 'sequential' => 1,
2228 'first_name' => 'abc5',
2229 'last_name' => 'xyz5',
2230 'contact_type' => 'Individual',
2231 'email' => 'woman5@yahoo.com',
2232 'api.phone.create' => array(
2233 array('phone' => '03-231 07 95'),
2234 array('phone' => '03-232 51 62'),
2235 ),
2236 'api.website.create' => array(
2237 'url' => 'http://civicrm.org',
2238 ),
2239 );
2240 $result = $this->callAPISuccess('Contact', 'create', $params);
2241
2242 // I could try to parse the result to see whether the two phone numbers
2243 // and the website are there, but I am not sure about the correct format.
2244 // So I will just fetch it again before checking.
2245 // See also http://forum.civicrm.org/index.php/topic,35393.0.html
2246 $params = array(
2247 'sequential' => 1,
2248 'id' => $result['id'],
2249 'api.website.get' => array(),
2250 'api.phone.get' => array(),
2251 );
2252 $result = $this->callAPISuccess('Contact', 'get', $params);
2253
2254 // delete the contact
2255 $this->callAPISuccess('contact', 'delete', $result);
2256
2257 $this->assertEquals(2, $result['values'][0]['api.phone.get']['count']);
2258 $this->assertEquals(1, $result['values'][0]['api.website.get']['count']);
2259 }
2260
2261 /**
2262 * Test retrieving an individual with chained array syntax.
2263 */
2264 public function testGetIndividualWithChainedArraysFormats() {
2265 $description = "This demonstrates the usage of chained api functions.\nIn this case no notes or custom fields have been created.";
2266 $subfile = "APIChainedArrayFormats";
2267 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
2268 $params['custom_' . $ids['custom_field_id']] = "custom string";
2269
2270 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2271 $params = array(
2272 'first_name' => 'abc3',
2273 'last_name' => 'xyz3',
2274 'contact_type' => 'Individual',
2275 'email' => 'man3@yahoo.com',
2276 'api.contribution.create' => array(
2277 'receive_date' => '2010-01-01',
2278 'total_amount' => 100.00,
2279 'financial_type_id' => $this->_financialTypeId,
2280 'payment_instrument_id' => 1,
2281 'non_deductible_amount' => 10.00,
2282 'fee_amount' => 50.00,
2283 'net_amount' => 90.00,
2284 'source' => 'SSF',
2285 'contribution_status_id' => 1,
2286 ),
2287 'api.contribution.create.1' => array(
2288 'receive_date' => '2011-01-01',
2289 'total_amount' => 120.00,
2290 'financial_type_id' => $this->_financialTypeId,
2291 'payment_instrument_id' => 1,
2292 'non_deductible_amount' => 10.00,
2293 'fee_amount' => 50.00,
2294 'net_amount' => 90.00,
2295 'source' => 'SSF',
2296 'contribution_status_id' => 1,
2297 ),
2298 'api.website.create' => array(
2299 array(
2300 'url' => "http://civicrm.org",
2301 ),
2302 ),
2303 );
2304
2305 $result = $this->callAPISuccess('Contact', 'create', $params);
2306 $params = array(
2307 'id' => $result['id'],
2308 'api.website.getValue' => array('return' => 'url'),
2309 'api.Contribution.getCount' => array(),
2310 'api.CustomValue.get' => 1,
2311 'api.Note.get' => 1,
2312 'api.Membership.getCount' => array(),
2313 );
2314 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
2315 $this->assertEquals(2, $result['values'][$result['id']]['api.Contribution.getCount']);
2316 $this->assertEquals(0, $result['values'][$result['id']]['api.Note.get']['is_error']);
2317 $this->assertEquals("http://civicrm.org", $result['values'][$result['id']]['api.website.getValue']);
2318
2319 $this->callAPISuccess('contact', 'delete', $result);
2320 $this->customGroupDelete($ids['custom_group_id']);
2321 $this->customGroupDelete($moreIDs['custom_group_id']);
2322 }
2323
2324 /**
2325 * Test complex chaining.
2326 */
2327 public function testGetIndividualWithChainedArraysAndMultipleCustom() {
2328 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
2329 $params['custom_' . $ids['custom_field_id']] = "custom string";
2330 $moreIDs = $this->CustomGroupMultipleCreateWithFields();
2331 $andMoreIDs = $this->CustomGroupMultipleCreateWithFields(array(
2332 'title' => "another group",
2333 'name' => 'another name',
2334 ));
2335 $description = "This demonstrates the usage of chained api functions with multiple custom fields.";
2336 $subfile = "APIChainedArrayMultipleCustom";
2337 $params = array(
2338 'first_name' => 'abc3',
2339 'last_name' => 'xyz3',
2340 'contact_type' => 'Individual',
2341 'email' => 'man3@yahoo.com',
2342 'api.contribution.create' => array(
2343 'receive_date' => '2010-01-01',
2344 'total_amount' => 100.00,
2345 'financial_type_id' => 1,
2346 'payment_instrument_id' => 1,
2347 'non_deductible_amount' => 10.00,
2348 'fee_amount' => 50.00,
2349 'net_amount' => 90.00,
2350 'trxn_id' => 12345,
2351 'invoice_id' => 67890,
2352 'source' => 'SSF',
2353 'contribution_status_id' => 1,
2354 ),
2355 'api.contribution.create.1' => array(
2356 'receive_date' => '2011-01-01',
2357 'total_amount' => 120.00,
2358 'financial_type_id' => 1,
2359 'payment_instrument_id' => 1,
2360 'non_deductible_amount' => 10.00,
2361 'fee_amount' => 50.00,
2362 'net_amount' => 90.00,
2363 'trxn_id' => 12335,
2364 'invoice_id' => 67830,
2365 'source' => 'SSF',
2366 'contribution_status_id' => 1,
2367 ),
2368 'api.website.create' => array(
2369 array(
2370 'url' => "http://civicrm.org",
2371 ),
2372 ),
2373 'custom_' . $ids['custom_field_id'] => "value 1",
2374 'custom_' . $moreIDs['custom_field_id'][0] => "value 2",
2375 'custom_' . $moreIDs['custom_field_id'][1] => "warm beer",
2376 'custom_' . $andMoreIDs['custom_field_id'][1] => "vegemite",
2377 );
2378
2379 $result = $this->callAPISuccess('Contact', 'create', $params);
2380 $result = $this->callAPISuccess('Contact', 'create', array(
2381 'contact_type' => 'Individual',
2382 'id' => $result['id'],
2383 'custom_' .
2384 $moreIDs['custom_field_id'][0] => "value 3",
2385 'custom_' .
2386 $ids['custom_field_id'] => "value 4",
2387 ));
2388
2389 $params = array(
2390 'id' => $result['id'],
2391 'api.website.getValue' => array('return' => 'url'),
2392 'api.Contribution.getCount' => array(),
2393 'api.CustomValue.get' => 1,
2394 );
2395 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
2396
2397 $this->customGroupDelete($ids['custom_group_id']);
2398 $this->customGroupDelete($moreIDs['custom_group_id']);
2399 $this->customGroupDelete($andMoreIDs['custom_group_id']);
2400 $this->assertEquals(0, $result['values'][$result['id']]['api.CustomValue.get']['is_error']);
2401 $this->assertEquals('http://civicrm.org', $result['values'][$result['id']]['api.website.getValue']);
2402 }
2403
2404 /**
2405 * Test checks usage of $values to pick & choose inputs.
2406 */
2407 public function testChainingValuesCreate() {
2408 $description = "This demonstrates the usage of chained api functions. Specifically it has one 'parent function' &
2409 2 child functions - one receives values from the parent (Contact) and the other child (Tag).";
2410 $subfile = "APIChainedArrayValuesFromSiblingFunction";
2411 $params = array(
2412 'display_name' => 'batman',
2413 'contact_type' => 'Individual',
2414 'api.tag.create' => array(
2415 'name' => '$value.id',
2416 'description' => '$value.display_name',
2417 'format.only_id' => 1,
2418 ),
2419 'api.entity_tag.create' => array('tag_id' => '$value.api.tag.create'),
2420 );
2421 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__, __FILE__, $description, $subfile);
2422 $this->assertEquals(0, $result['values'][$result['id']]['api.entity_tag.create']['is_error']);
2423
2424 $tablesToTruncate = array(
2425 'civicrm_contact',
2426 'civicrm_activity',
2427 'civicrm_entity_tag',
2428 'civicrm_tag',
2429 );
2430 $this->quickCleanup($tablesToTruncate, TRUE);
2431 }
2432
2433 /**
2434 * Test TrueFalse format - I couldn't come up with an easy way to get an error on Get.
2435 */
2436 public function testContactGetFormatIsSuccessTrue() {
2437 $this->createContactFromXML();
2438 $description = "This demonstrates use of the 'format.is_success' param.
2439 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2440 $subfile = "FormatIsSuccess_True";
2441 $params = array('id' => 17, 'format.is_success' => 1);
2442 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
2443 $this->assertEquals(1, $result);
2444 $this->callAPISuccess('Contact', 'Delete', $params);
2445 }
2446
2447 /**
2448 * Test TrueFalse format.
2449 */
2450 public function testContactCreateFormatIsSuccessFalse() {
2451
2452 $description = "This demonstrates use of the 'format.is_success' param.
2453 This param causes only the success or otherwise of the function to be returned as BOOLEAN";
2454 $subfile = "FormatIsSuccess_Fail";
2455 $params = array('id' => 500, 'format.is_success' => 1);
2456 $result = $this->callAPIAndDocument('Contact', 'Create', $params, __FUNCTION__, __FILE__, $description, $subfile);
2457 $this->assertEquals(0, $result);
2458 }
2459
2460 /**
2461 * Test long display names.
2462 *
2463 * CRM-21258
2464 */
2465 public function testContactCreateLongDisplayName() {
2466 $result = $this->callAPISuccess('Contact', 'Create', array(
2467 'first_name' => str_pad('a', 64, 'a'),
2468 'last_name' => str_pad('a', 64, 'a'),
2469 'contact_type' => 'Individual',
2470 ));
2471 $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $result['values'][$result['id']]['display_name']);
2472 $this->assertEquals('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa', $result['values'][$result['id']]['sort_name']);
2473 }
2474
2475 /**
2476 * Test Single Entity format.
2477 */
2478 public function testContactGetSingleEntityArray() {
2479 $this->createContactFromXML();
2480 $description = "This demonstrates use of the 'format.single_entity_array' param.
2481 This param causes the only contact to be returned as an array without the other levels.
2482 It will be ignored if there is not exactly 1 result";
2483 $subfile = "GetSingleContact";
2484 $params = array('id' => 17);
2485 $result = $this->callAPIAndDocument('Contact', 'GetSingle', $params, __FUNCTION__, __FILE__, $description, $subfile);
2486 $this->assertEquals('Test Contact', $result['display_name']);
2487 $this->callAPISuccess('Contact', 'Delete', $params);
2488 }
2489
2490 /**
2491 * Test Single Entity format.
2492 */
2493 public function testContactGetFormatCountOnly() {
2494 $this->createContactFromXML();
2495 $description = "This demonstrates use of the 'getCount' action.
2496 This param causes the count of the only function to be returned as an integer.";
2497 $params = array('id' => 17);
2498 $result = $this->callAPIAndDocument('Contact', 'GetCount', $params, __FUNCTION__, __FILE__, $description,
2499 'GetCountContact');
2500 $this->assertEquals('1', $result);
2501 $this->callAPISuccess('Contact', 'Delete', $params);
2502 }
2503
2504 /**
2505 * Test id only format.
2506 */
2507 public function testContactGetFormatIDOnly() {
2508 $this->createContactFromXML();
2509 $description = "This demonstrates use of the 'format.id_only' param.
2510 This param causes the id of the only entity to be returned as an integer.
2511 It will be ignored if there is not exactly 1 result";
2512 $subfile = "FormatOnlyID";
2513 $params = array('id' => 17, 'format.only_id' => 1);
2514 $result = $this->callAPIAndDocument('Contact', 'Get', $params, __FUNCTION__, __FILE__, $description, $subfile);
2515 $this->assertEquals('17', $result);
2516 $this->callAPISuccess('Contact', 'Delete', $params);
2517 }
2518
2519 /**
2520 * Test id only format.
2521 */
2522 public function testContactGetFormatSingleValue() {
2523 $this->createContactFromXML();
2524 $description = "This demonstrates use of the 'format.single_value' param.
2525 This param causes only a single value of the only entity to be returned as an string.
2526 It will be ignored if there is not exactly 1 result";
2527 $subFile = "FormatSingleValue";
2528 $params = array('id' => 17, 'return' => 'display_name');
2529 $result = $this->callAPIAndDocument('Contact', 'getvalue', $params, __FUNCTION__, __FILE__, $description, $subFile);
2530 $this->assertEquals('Test Contact', $result);
2531 $this->callAPISuccess('Contact', 'Delete', $params);
2532 }
2533
2534 /**
2535 * Test that permissions are respected when creating contacts.
2536 */
2537 public function testContactCreationPermissions() {
2538 $params = array(
2539 'contact_type' => 'Individual',
2540 'first_name' => 'Foo',
2541 'last_name' => 'Bear',
2542 'check_permissions' => TRUE,
2543 );
2544 $config = CRM_Core_Config::singleton();
2545 $config->userPermissionClass->permissions = array('access CiviCRM');
2546 $result = $this->callAPIFailure('contact', 'create', $params);
2547 $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');
2548
2549 $config->userPermissionClass->permissions = array('access CiviCRM', 'add contacts', 'import contacts');
2550 $this->callAPISuccess('contact', 'create', $params);
2551 }
2552
2553 /**
2554 * Test that delete with skip undelete respects permissions.
2555 */
2556 public function testContactDeletePermissions() {
2557 $contactID = $this->individualCreate();
2558 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM');
2559 $this->callAPIFailure('Contact', 'delete', array(
2560 'id' => $contactID,
2561 'check_permissions' => 1,
2562 'skip_undelete' => 1,
2563 ));
2564 $this->callAPISuccess('Contact', 'delete', array(
2565 'id' => $contactID,
2566 'check_permissions' => 0,
2567 'skip_undelete' => 1,
2568 ));
2569 }
2570
2571 /**
2572 * Test update with check permissions set.
2573 */
2574 public function testContactUpdatePermissions() {
2575 $params = array(
2576 'contact_type' => 'Individual',
2577 'first_name' => 'Foo',
2578 'last_name' => 'Bear',
2579 'check_permissions' => TRUE,
2580 );
2581 $result = $this->callAPISuccess('contact', 'create', $params);
2582 $config = CRM_Core_Config::singleton();
2583 $params = array(
2584 'id' => $result['id'],
2585 'contact_type' => 'Individual',
2586 'last_name' => 'Bar',
2587 'check_permissions' => TRUE,
2588 );
2589
2590 $config->userPermissionClass->permissions = array('access CiviCRM');
2591 $result = $this->callAPIFailure('contact', 'update', $params);
2592 $this->assertEquals('Permission denied to modify contact record', $result['error_message']);
2593
2594 $config->userPermissionClass->permissions = array(
2595 'access CiviCRM',
2596 'add contacts',
2597 'view all contacts',
2598 'edit all contacts',
2599 'import contacts',
2600 );
2601 $this->callAPISuccess('contact', 'update', $params);
2602 }
2603
2604 /**
2605 * Set up helper to create a contact.
2606 */
2607 public function createContactFromXML() {
2608 // Insert a row in civicrm_contact creating contact 17.
2609 $op = new PHPUnit_Extensions_Database_Operation_Insert();
2610 $op->execute($this->_dbconn,
2611 $this->createXMLDataSet(
2612 dirname(__FILE__) . '/dataset/contact_17.xml'
2613 )
2614 );
2615 }
2616
2617 /**
2618 * Test contact proximity api.
2619 */
2620 public function testContactProximity() {
2621 // first create a contact with a SF location with a specific
2622 // geocode
2623 $contactID = $this->organizationCreate();
2624
2625 // now create the address
2626 $params = array(
2627 'street_address' => '123 Main Street',
2628 'city' => 'San Francisco',
2629 'is_primary' => 1,
2630 'country_id' => 1228,
2631 'state_province_id' => 1004,
2632 'geo_code_1' => '37.79',
2633 'geo_code_2' => '-122.40',
2634 'location_type_id' => 1,
2635 'contact_id' => $contactID,
2636 );
2637
2638 $result = $this->callAPISuccess('address', 'create', $params);
2639 $this->assertEquals(1, $result['count']);
2640
2641 // now do a proximity search with a close enough geocode and hope to match
2642 // that specific contact only!
2643 $proxParams = array(
2644 'latitude' => 37.7,
2645 'longitude' => -122.3,
2646 'unit' => 'mile',
2647 'distance' => 10,
2648 );
2649 $result = $this->callAPISuccess('contact', 'proximity', $proxParams);
2650 $this->assertEquals(1, $result['count']);
2651 }
2652
2653 /**
2654 * Test that Ajax API permission is sufficient to access getquick api.
2655 *
2656 * (note that getquick api is required for autocomplete & has ACL permissions applied)
2657 */
2658 public function testGetquickPermissionCRM13744() {
2659 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviEvent');
2660 $this->callAPIFailure('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2661 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access CiviCRM');
2662 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2663 CRM_Core_Config::singleton()->userPermissionClass->permissions = array('access AJAX API');
2664 $this->callAPISuccess('contact', 'getquick', array('name' => 'b', 'check_permissions' => TRUE));
2665 }
2666
2667 /**
2668 * Test that getquick returns contacts with an exact first name match first.
2669 *
2670 * The search string 'b' & 'bob' both return ordered by sort_name if includeOrderByClause
2671 * is true (default) but if it is false then matches are returned in ID order.
2672 *
2673 * @dataProvider getSearchSortOptions
2674 */
2675 public function testGetQuickExactFirst($searchParameters, $settings, $firstContact, $secondContact = NULL) {
2676 $this->getQuickSearchSampleData();
2677 $this->callAPISuccess('Setting', 'create', $settings);
2678 $result = $this->callAPISuccess('contact', 'getquick', $searchParameters);
2679 $this->assertEquals($firstContact, $result['values'][0]['sort_name']);
2680 $this->assertEquals($secondContact, $result['values'][1]['sort_name']);
2681 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE));
2682 }
2683
2684 public function getSearchSortOptions() {
2685 $firstAlphabeticalContactBySortName = 'A Bobby, Bobby';
2686 $secondAlphabeticalContactBySortName = 'Aadvark, Bob';
2687 $secondAlphabeticalContactWithEmailBySortName = 'Bob, Bob';
2688 $firstAlphabeticalContactFirstNameBob = 'Aadvark, Bob';
2689 $secondAlphabeticalContactFirstNameBob = 'Bob, Bob';
2690 $firstByIDContactFirstNameBob = 'Bob, Bob';
2691 $secondByIDContactFirstNameBob = 'K Bobby, Bob';
2692 $firstContactByID = 'Bob, Bob';
2693 $secondContactByID = 'E Bobby, Bobby';
2694 $bobLikeEmail = 'A Bobby, Bobby';
2695
2696 return array(
2697 'empty_search_basic' => array(
2698 'search_parameters' => array('name' => '%'),
2699 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2700 'first_contact' => $firstAlphabeticalContactBySortName,
2701 'second_contact' => $secondAlphabeticalContactBySortName,
2702 ),
2703 'empty_search_basic_no_wildcard' => array(
2704 'search_parameters' => array('name' => '%'),
2705 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2706 'first_contact' => $firstAlphabeticalContactBySortName,
2707 'second_contact' => $secondAlphabeticalContactBySortName,
2708 ),
2709 'single_letter_search_basic' => array(
2710 'search_parameters' => array('name' => 'b'),
2711 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2712 'first_contact' => $firstAlphabeticalContactBySortName,
2713 'second_contact' => $secondAlphabeticalContactBySortName,
2714 ),
2715 'bob_search_basic' => array(
2716 'search_parameters' => array('name' => 'bob'),
2717 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2718 'first_contact' => $firstAlphabeticalContactBySortName,
2719 'second_contact' => $secondAlphabeticalContactBySortName,
2720 ),
2721 'bob_search_no_orderby' => array(
2722 'search_parameters' => array('name' => 'bob'),
2723 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => FALSE),
2724 'first_contact' => $firstContactByID,
2725 'second_contact' => $secondContactByID,
2726 ),
2727 'bob_search_no_wildcard' => array(
2728 'search_parameters' => array('name' => 'bob'),
2729 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2730 'second_contact' => $bobLikeEmail,
2731 'first_contact' => $secondAlphabeticalContactFirstNameBob,
2732 ),
2733 // This should be the same as just no wildcard as if we had an exactMatch while searching by
2734 // sort name it would rise to the top CRM-19547
2735 'bob_search_no_wildcard_no_orderby' => array(
2736 'search_parameters' => array('name' => 'bob'),
2737 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2738 'second_contact' => $bobLikeEmail,
2739 'first_contact' => $secondAlphabeticalContactFirstNameBob,
2740 ),
2741 'first_name_search_basic' => array(
2742 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2743 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => TRUE),
2744 'first_contact' => $firstAlphabeticalContactFirstNameBob,
2745 'second_contact' => $secondAlphabeticalContactFirstNameBob,
2746 ),
2747 'first_name_search_no_wildcard' => array(
2748 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2749 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2750 'first_contact' => $firstAlphabeticalContactFirstNameBob,
2751 'second_contact' => $secondAlphabeticalContactFirstNameBob,
2752 ),
2753 'first_name_search_no_orderby' => array(
2754 'search_parameters' => array('name' => 'bob', 'field_name' => 'first_name'),
2755 'settings' => array('includeWildCardInName' => TRUE, 'includeOrderByClause' => FALSE),
2756 'first_contact' => $firstByIDContactFirstNameBob,
2757 'second_contact' => $secondByIDContactFirstNameBob,
2758 ),
2759 'email_search_basic' => array(
2760 'search_parameters' => array('name' => 'bob', 'field_name' => 'email', 'table_name' => 'eml'),
2761 'settings' => array('includeWildCardInName' => FALSE, 'includeOrderByClause' => TRUE),
2762 'first_contact' => $firstAlphabeticalContactBySortName,
2763 'second_contact' => $secondAlphabeticalContactWithEmailBySortName,
2764 ),
2765 );
2766 }
2767
2768 /**
2769 * Test that getquick returns contacts with an exact first name match first.
2770 */
2771 public function testGetQuickEmail() {
2772 $this->getQuickSearchSampleData();
2773 $loggedInContactID = $this->createLoggedInUser();
2774 $result = $this->callAPISuccess('contact', 'getquick', array(
2775 'name' => 'c',
2776 ));
2777 $expectedData = array(
2778 'A Bobby, Bobby :: bob@bobby.com',
2779 'Bob, Bob :: bob@bob.com',
2780 'C Bobby, Bobby',
2781 'H Bobby, Bobby :: bob@h.com',
2782 'Second Domain',
2783 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
2784 );
2785 $this->assertEquals(6, $result['count']);
2786 foreach ($expectedData as $index => $value) {
2787 $this->assertEquals($value, $result['values'][$index]['data']);
2788 }
2789 $result = $this->callAPISuccess('contact', 'getquick', array(
2790 'name' => 'h.',
2791 ));
2792 $expectedData = array(
2793 'H Bobby, Bobby :: bob@h.com',
2794 );
2795 foreach ($expectedData as $index => $value) {
2796 $this->assertEquals($value, $result['values'][$index]['data']);
2797 }
2798 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => FALSE));
2799 $result = $this->callAPISuccess('contact', 'getquick', array(
2800 'name' => 'h.',
2801 ));
2802 $this->callAPISuccess('Setting', 'create', array('includeWildCardInName' => TRUE));
2803 $this->assertEquals(0, $result['count']);
2804 }
2805
2806 /**
2807 * Test that getquick returns contacts with an exact first name match first.
2808 */
2809 public function testGetQuickEmailACL() {
2810 $this->getQuickSearchSampleData();
2811 $loggedInContactID = $this->createLoggedInUser();
2812 CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
2813 $result = $this->callAPISuccess('contact', 'getquick', array(
2814 'name' => 'c',
2815 ));
2816 $this->assertEquals(0, $result['count']);
2817
2818 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
2819 CRM_Contact_BAO_Contact_Permission::cache($loggedInContactID, CRM_Core_Permission::VIEW, TRUE);
2820 $result = $this->callAPISuccess('contact', 'getquick', array(
2821 'name' => 'c',
2822 ));
2823
2824 // Without the acl it would be 6 like the previous email getquick test.
2825 $this->assertEquals(5, $result['count']);
2826 $expectedData = array(
2827 'A Bobby, Bobby :: bob@bobby.com',
2828 'Bob, Bob :: bob@bob.com',
2829 'C Bobby, Bobby',
2830 'Second Domain',
2831 $this->callAPISuccessGetValue('Contact', array('id' => $loggedInContactID, 'return' => 'last_name')) . ', Logged In :: anthony_anderson@civicrm.org',
2832 );
2833 foreach ($expectedData as $index => $value) {
2834 $this->assertEquals($value, $result['values'][$index]['data']);
2835 }
2836 }
2837
2838 /**
2839 * Test that getquick returns contacts with an exact first name match first.
2840 */
2841 public function testGetQuickExternalID() {
2842 $this->getQuickSearchSampleData();
2843 $result = $this->callAPISuccess('contact', 'getquick', array(
2844 'name' => 'b',
2845 'field_name' => 'external_identifier',
2846 'table_name' => 'cc',
2847 ));
2848 $this->assertEquals(0, $result['count']);
2849 $result = $this->callAPISuccess('contact', 'getquick', array(
2850 'name' => 'abc',
2851 'field_name' => 'external_identifier',
2852 'table_name' => 'cc',
2853 ));
2854 $this->assertEquals(1, $result['count']);
2855 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2856 }
2857
2858 /**
2859 * Test that getquick returns contacts with an exact first name match first.
2860 */
2861 public function testGetQuickID() {
2862 $max = CRM_Core_DAO::singleValueQuery("SELECT max(id) FROM civicrm_contact");
2863 $this->getQuickSearchSampleData();
2864 $result = $this->callAPISuccess('contact', 'getquick', array(
2865 'name' => $max + 2,
2866 'field_name' => 'id',
2867 'table_name' => 'cc',
2868 ));
2869 $this->assertEquals(1, $result['count']);
2870 $this->assertEquals('E Bobby, Bobby', $result['values'][0]['sort_name']);
2871 $result = $this->callAPISuccess('contact', 'getquick', array(
2872 'name' => $max + 2,
2873 'field_name' => 'contact_id',
2874 'table_name' => 'cc',
2875 ));
2876 $this->assertEquals(1, $result['count']);
2877 $this->assertEquals('E Bobby, Bobby', $result['values'][0]['sort_name']);
2878 }
2879
2880 /**
2881 * Test that getquick returns contacts with an exact first name match first.
2882 *
2883 * Depending on the setting the sort name sort might click in next or not - test!
2884 */
2885 public function testGetQuickFirstName() {
2886 $this->getQuickSearchSampleData();
2887 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2888 $result = $this->callAPISuccess('contact', 'getquick', array(
2889 'name' => 'Bob',
2890 'field_name' => 'first_name',
2891 'table_name' => 'cc',
2892 ));
2893 $expected = array(
2894 'Aadvark, Bob',
2895 'Bob, Bob',
2896 'K Bobby, Bob',
2897 'A Bobby, Bobby',
2898 );
2899
2900 foreach ($expected as $index => $value) {
2901 $this->assertEquals($value, $result['values'][$index]['sort_name']);
2902 }
2903 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
2904 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2905 $this->assertEquals('Bob, Bob', $result['values'][0]['sort_name']);
2906 $this->assertEquals('E Bobby, Bobby', $result['values'][1]['sort_name']);
2907 }
2908
2909 /**
2910 * Test that getquick applies ACLs.
2911 */
2912 public function testGetQuickFirstNameACLs() {
2913 $this->getQuickSearchSampleData();
2914 $userID = $this->createLoggedInUser();
2915 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE, 'search_autocomplete_count' => 15));
2916 CRM_Core_Config::singleton()->userPermissionClass->permissions = array();
2917 $result = $this->callAPISuccess('contact', 'getquick', array(
2918 'name' => 'Bob',
2919 'field_name' => 'first_name',
2920 'table_name' => 'cc',
2921 ));
2922 $this->assertEquals(0, $result['count']);
2923
2924 $this->hookClass->setHook('civicrm_aclWhereClause', array($this, 'aclWhereNoBobH'));
2925 CRM_Contact_BAO_Contact_Permission::cache($userID, CRM_Core_Permission::VIEW, TRUE);
2926 $result = $this->callAPISuccess('contact', 'getquick', array(
2927 'name' => 'Bob',
2928 'field_name' => 'first_name',
2929 'table_name' => 'cc',
2930 ));
2931 $this->assertEquals('K Bobby, Bob', $result['values'][2]['sort_name']);
2932 // Without the ACL 9 would be bob@h.com.
2933 $this->assertEquals('I Bobby, Bobby', $result['values'][10]['sort_name']);
2934 }
2935
2936 /**
2937 * Full results returned.
2938 * @implements CRM_Utils_Hook::aclWhereClause
2939 *
2940 * @param string $type
2941 * @param array $tables
2942 * @param array $whereTables
2943 * @param int $contactID
2944 * @param string $where
2945 */
2946 public function aclWhereNoBobH($type, &$tables, &$whereTables, &$contactID, &$where) {
2947 $where = " (email <> 'bob@h.com' OR email IS NULL) ";
2948 $whereTables['civicrm_email'] = "LEFT JOIN civicrm_email e ON contact_a.id = e.contact_id";
2949 }
2950
2951 /**
2952 * Test that getquick returns contacts with an exact last name match first.
2953 */
2954 public function testGetQuickLastName() {
2955 $this->getQuickSearchSampleData();
2956 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => TRUE));
2957 $result = $this->callAPISuccess('contact', 'getquick', array(
2958 'name' => 'Bob',
2959 'field_name' => 'last_name',
2960 'table_name' => 'cc',
2961 ));
2962 $expected = array(
2963 'Bob, Bob',
2964 'A Bobby, Bobby',
2965 'B Bobby, Bobby',
2966 );
2967
2968 foreach ($expected as $index => $value) {
2969 $this->assertEquals($value, $result['values'][$index]['sort_name']);
2970 }
2971 $this->callAPISuccess('Setting', 'create', array('includeOrderByClause' => FALSE));
2972 $result = $this->callAPISuccess('contact', 'getquick', array('name' => 'bob'));
2973 $this->assertEquals('Bob, Bob :: bob@bob.com', $result['values'][0]['data']);
2974 }
2975
2976 /**
2977 * Test that getquick returns contacts by city.
2978 */
2979 public function testGetQuickCity() {
2980 $this->getQuickSearchSampleData();
2981 $result = $this->callAPISuccess('contact', 'getquick', array(
2982 'name' => 'o',
2983 'field_name' => 'city',
2984 'table_name' => 'sts',
2985 ));
2986 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
2987 $result = $this->callAPISuccess('contact', 'getquick', array(
2988 'name' => 'n',
2989 'field_name' => 'city',
2990 'table_name' => 'sts',
2991 ));
2992 $this->assertEquals('B Bobby, Bobby :: Toronto', $result['values'][0]['data']);
2993 $this->assertEquals('C Bobby, Bobby :: Whanganui', $result['values'][1]['data']);
2994 }
2995
2996 /**
2997 * Set up some sample data for testing quicksearch.
2998 */
2999 public function getQuickSearchSampleData() {
3000 $contacts = array(
3001 array('first_name' => 'Bob', 'last_name' => 'Bob', 'external_identifier' => 'abc', 'email' => 'bob@bob.com'),
3002 array('first_name' => 'Bobby', 'last_name' => 'E Bobby', 'external_identifier' => 'abcd'),
3003 array(
3004 'first_name' => 'Bobby',
3005 'last_name' => 'B Bobby',
3006 'external_identifier' => 'bcd',
3007 'api.address.create' => array(
3008 'street_address' => 'Sesame Street',
3009 'city' => 'Toronto',
3010 'location_type_id' => 1,
3011 ),
3012 ),
3013 array(
3014 'first_name' => 'Bobby',
3015 'last_name' => 'C Bobby',
3016 'external_identifier' => 'bcde',
3017 'api.address.create' => array(
3018 'street_address' => 'Te huarahi',
3019 'city' => 'Whanganui',
3020 'location_type_id' => 1,
3021 ),
3022 ),
3023 array('first_name' => 'Bobby', 'last_name' => 'D Bobby', 'external_identifier' => 'efg'),
3024 array('first_name' => 'Bobby', 'last_name' => 'A Bobby', 'external_identifier' => 'hij', 'email' => 'bob@bobby.com'),
3025 array('first_name' => 'Bobby', 'last_name' => 'F Bobby', 'external_identifier' => 'klm'),
3026 array('first_name' => 'Bobby', 'last_name' => 'G Bobby', 'external_identifier' => 'nop'),
3027 array('first_name' => 'Bobby', 'last_name' => 'H Bobby', 'external_identifier' => 'qrs', 'email' => 'bob@h.com'),
3028 array('first_name' => 'Bobby', 'last_name' => 'I Bobby'),
3029 array('first_name' => 'Bobby', 'last_name' => 'J Bobby'),
3030 array('first_name' => 'Bob', 'last_name' => 'K Bobby', 'external_identifier' => 'bcdef'),
3031 array('first_name' => 'Bob', 'last_name' => 'Aadvark'),
3032 );
3033 foreach ($contacts as $type => $contact) {
3034 $contact['contact_type'] = 'Individual';
3035 $this->callAPISuccess('Contact', 'create', $contact);
3036 }
3037 }
3038
3039 /**
3040 * Test get ref api - gets a list of references to an entity.
3041 */
3042 public function testGetReferenceCounts() {
3043 $result = $this->callAPISuccess('Contact', 'create', array(
3044 'first_name' => 'Testily',
3045 'last_name' => 'McHaste',
3046 'contact_type' => 'Individual',
3047 'api.Address.replace' => array(
3048 'values' => array(),
3049 ),
3050 'api.Email.replace' => array(
3051 'values' => array(
3052 array(
3053 'email' => 'spam@dev.null',
3054 'is_primary' => 0,
3055 'location_type_id' => 1,
3056 ),
3057 ),
3058 ),
3059 'api.Phone.replace' => array(
3060 'values' => array(
3061 array(
3062 'phone' => '234-567-0001',
3063 'is_primary' => 1,
3064 'location_type_id' => 1,
3065 ),
3066 array(
3067 'phone' => '234-567-0002',
3068 'is_primary' => 0,
3069 'location_type_id' => 1,
3070 ),
3071 ),
3072 ),
3073 ));
3074
3075 //$dao = new CRM_Contact_BAO_Contact();
3076 //$dao->id = $result['id'];
3077 //$this->assertTrue((bool) $dao->find(TRUE));
3078 //
3079 //$refCounts = $dao->getReferenceCounts();
3080 //$this->assertTrue(is_array($refCounts));
3081 //$refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts);
3082
3083 $refCounts = $this->callAPISuccess('Contact', 'getrefcount', array(
3084 'id' => $result['id'],
3085 ));
3086 $refCountsIdx = CRM_Utils_Array::index(array('name'), $refCounts['values']);
3087
3088 $this->assertEquals(1, $refCountsIdx['sql:civicrm_email:contact_id']['count']);
3089 $this->assertEquals('civicrm_email', $refCountsIdx['sql:civicrm_email:contact_id']['table']);
3090 $this->assertEquals(2, $refCountsIdx['sql:civicrm_phone:contact_id']['count']);
3091 $this->assertEquals('civicrm_phone', $refCountsIdx['sql:civicrm_phone:contact_id']['table']);
3092 $this->assertTrue(!isset($refCountsIdx['sql:civicrm_address:contact_id']));
3093 }
3094
3095 /**
3096 * Test the use of sql operators.
3097 */
3098 public function testSQLOperatorsOnContactAPI() {
3099 $this->individualCreate();
3100 $this->organizationCreate();
3101 $this->householdCreate();
3102 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NOT NULL' => TRUE)));
3103 $this->assertEquals($contacts['count'], CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NOT NULL'));
3104 $contacts = $this->callAPISuccess('contact', 'get', array('legal_name' => array('IS NULL' => TRUE)));
3105 $this->assertEquals($contacts['count'], CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact WHERE legal_name IS NULL'));
3106 }
3107
3108 /**
3109 * CRM-14743 - test api respects search operators.
3110 */
3111 public function testGetModifiedDateByOperators() {
3112 $preExistingContactCount = CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact');
3113 $contact1 = $this->individualCreate();
3114 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01', modified_date = '2013-01-01' WHERE id = " . $contact1;
3115 CRM_Core_DAO::executeQuery($sql);
3116 $contact2 = $this->individualCreate();
3117 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01', modified_date = '2013-02-01' WHERE id = " . $contact2;
3118 CRM_Core_DAO::executeQuery($sql);
3119 $contact3 = $this->householdCreate();
3120 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01', modified_date = '2013-03-01' WHERE id = " . $contact3;
3121 CRM_Core_DAO::executeQuery($sql);
3122 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('<' => '2014-01-01')));
3123 $this->assertEquals($contacts['count'], 3);
3124 $contacts = $this->callAPISuccess('contact', 'get', array('modified_date' => array('>' => '2014-01-01')));
3125 $this->assertEquals($contacts['count'], $preExistingContactCount);
3126 }
3127
3128 /**
3129 * CRM-14743 - test api respects search operators.
3130 */
3131 public function testGetCreatedDateByOperators() {
3132 $preExistingContactCount = CRM_Core_DAO::singleValueQuery('select count(*) FROM civicrm_contact');
3133 $contact1 = $this->individualCreate();
3134 $sql = "UPDATE civicrm_contact SET created_date = '2012-01-01' WHERE id = " . $contact1;
3135 CRM_Core_DAO::executeQuery($sql);
3136 $contact2 = $this->individualCreate();
3137 $sql = "UPDATE civicrm_contact SET created_date = '2012-02-01' WHERE id = " . $contact2;
3138 CRM_Core_DAO::executeQuery($sql);
3139 $contact3 = $this->householdCreate();
3140 $sql = "UPDATE civicrm_contact SET created_date = '2012-03-01' WHERE id = " . $contact3;
3141 CRM_Core_DAO::executeQuery($sql);
3142 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('<' => '2014-01-01')));
3143 $this->assertEquals($contacts['count'], 3);
3144 $contacts = $this->callAPISuccess('contact', 'get', array('created_date' => array('>' => '2014-01-01')));
3145 $this->assertEquals($contacts['count'], $preExistingContactCount);
3146 }
3147
3148 /**
3149 * CRM-14263 check that API is not affected by search profile related bug.
3150 */
3151 public function testReturnCityProfile() {
3152 $contactID = $this->individualCreate();
3153 CRM_Core_Config::singleton()->defaultSearchProfileID = 1;
3154 $this->callAPISuccess('address', 'create', array(
3155 'contact_id' => $contactID,
3156 'city' => 'Cool City',
3157 'location_type_id' => 1,
3158 ));
3159 $result = $this->callAPISuccess('contact', 'get', array('city' => 'Cool City', 'return' => 'contact_type'));
3160 $this->assertEquals(1, $result['count']);
3161 }
3162
3163 /**
3164 * CRM-15443 - ensure getlist api does not return deleted contacts.
3165 */
3166 public function testGetlistExcludeConditions() {
3167 $name = md5(time());
3168 $contact = $this->individualCreate(array('last_name' => $name));
3169 $this->individualCreate(array('last_name' => $name, 'is_deceased' => 1));
3170 $this->individualCreate(array('last_name' => $name, 'is_deleted' => 1));
3171 // We should get all but the deleted contact.
3172 $result = $this->callAPISuccess('contact', 'getlist', array('input' => $name));
3173 $this->assertEquals(2, $result['count']);
3174 // Force-exclude the deceased contact.
3175 $result = $this->callAPISuccess('contact', 'getlist', array(
3176 'input' => $name,
3177 'params' => array('is_deceased' => 0),
3178 ));
3179 $this->assertEquals(1, $result['count']);
3180 $this->assertEquals($contact, $result['values'][0]['id']);
3181 }
3182
3183 /**
3184 * Test contact getactions.
3185 */
3186 public function testGetActions() {
3187 $description = "Getting the available actions for an entity.";
3188 $result = $this->callAPIAndDocument($this->_entity, 'getactions', array(), __FUNCTION__, __FILE__, $description);
3189 $expected = array(
3190 'create',
3191 'delete',
3192 'get',
3193 'getactions',
3194 'getcount',
3195 'getfields',
3196 'getlist',
3197 'getoptions',
3198 'getquick',
3199 'getrefcount',
3200 'getsingle',
3201 'getvalue',
3202 'merge',
3203 'proximity',
3204 'replace',
3205 'setvalue',
3206 'update',
3207 );
3208 $deprecated = array(
3209 'update',
3210 'getquick',
3211 );
3212 foreach ($expected as $action) {
3213 $this->assertTrue(in_array($action, $result['values']), "Expected action $action");
3214 }
3215 foreach ($deprecated as $action) {
3216 $this->assertArrayKeyExists($action, $result['deprecated']);
3217 }
3218 }
3219
3220 /**
3221 * Test the duplicate check function.
3222 */
3223 public function testDuplicateCheck() {
3224 $harry = array(
3225 'first_name' => 'Harry',
3226 'last_name' => 'Potter',
3227 'email' => 'harry@hogwarts.edu',
3228 'contact_type' => 'Individual',
3229 );
3230 $this->callAPISuccess('Contact', 'create', $harry);
3231 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3232 'match' => $harry,
3233 ));
3234
3235 $this->assertEquals(1, $result['count']);
3236 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3237 'match' => array(
3238 'first_name' => 'Harry',
3239 'last_name' => 'Potter',
3240 'email' => 'no5@privet.drive',
3241 'contact_type' => 'Individual',
3242 ),
3243 ));
3244 $this->assertEquals(0, $result['count']);
3245 $this->callAPIFailure('Contact', 'create', array_merge($harry, array('dupe_check' => 1)));
3246 }
3247
3248 /**
3249 * Test the duplicate check function.
3250 */
3251 public function testDuplicateCheckRuleNotReserved() {
3252 $harry = array(
3253 'first_name' => 'Harry',
3254 'last_name' => 'Potter',
3255 'email' => 'harry@hogwarts.edu',
3256 'contact_type' => 'Individual',
3257 );
3258 $defaultRule = $this->callAPISuccess('RuleGroup', 'getsingle', array('used' => 'Unsupervised', 'is_reserved' => 1));
3259 $this->callAPISuccess('RuleGroup', 'create', array('id' => $defaultRule['id'], 'is_reserved' => 0));
3260 $this->callAPISuccess('Contact', 'create', $harry);
3261 $result = $this->callAPISuccess('Contact', 'duplicatecheck', array(
3262 'match' => $harry,
3263 ));
3264
3265 $this->assertEquals(1, $result['count']);
3266 $this->callAPISuccess('RuleGroup', 'create', array('id' => $defaultRule['id'], 'is_reserved' => 1));
3267 }
3268
3269 /**
3270 * Test variants on retrieving contact by type.
3271 */
3272 public function testGetByContactType() {
3273 $individual = $this->callAPISuccess('Contact', 'create', array(
3274 'email' => 'individual@test.com',
3275 'contact_type' => 'Individual',
3276 ));
3277 $household = $this->callAPISuccess('Contact', 'create', array(
3278 'household_name' => 'household@test.com',
3279 'contact_type' => 'Household',
3280 ));
3281 $organization = $this->callAPISuccess('Contact', 'create', array(
3282 'organization_name' => 'organization@test.com',
3283 'contact_type' => 'Organization',
3284 ));
3285 // Test with id - getsingle will throw an exception if not found
3286 $this->callAPISuccess('Contact', 'getsingle', array(
3287 'id' => $individual['id'],
3288 'contact_type' => 'Individual',
3289 ));
3290 $this->callAPISuccess('Contact', 'getsingle', array(
3291 'id' => $individual['id'],
3292 'contact_type' => array('IN' => array('Individual')),
3293 'return' => 'id',
3294 ));
3295 $this->callAPISuccess('Contact', 'getsingle', array(
3296 'id' => $organization['id'],
3297 'contact_type' => array('IN' => array('Individual', 'Organization')),
3298 ));
3299 // Test as array
3300 $result = $this->callAPISuccess('Contact', 'get', array(
3301 'contact_type' => array('IN' => array('Individual', 'Organization')),
3302 'options' => array('limit' => 0),
3303 'return' => 'id',
3304 ));
3305 $this->assertContains($organization['id'], array_keys($result['values']));
3306 $this->assertContains($individual['id'], array_keys($result['values']));
3307 $this->assertNotContains($household['id'], array_keys($result['values']));
3308 // Test as string
3309 $result = $this->callAPISuccess('Contact', 'get', array(
3310 'contact_type' => 'Household',
3311 'options' => array('limit' => 0),
3312 'return' => 'id',
3313 ));
3314 $this->assertNotContains($organization['id'], array_keys($result['values']));
3315 $this->assertNotContains($individual['id'], array_keys($result['values']));
3316 $this->assertContains($household['id'], array_keys($result['values']));
3317 }
3318
3319 /**
3320 * Test merging 2 contacts.
3321 *
3322 * Someone kindly bequethed us the legacy of mixed up use of main_id & other_id
3323 * in the params for contact.merge api.
3324 *
3325 * This test protects that legacy.
3326 */
3327 public function testMergeBizzareOldParams() {
3328 $this->createLoggedInUser();
3329 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params);
3330 $mainContact = $this->callAPISuccess('contact', 'create', $this->_params);
3331 $this->callAPISuccess('contact', 'merge', array(
3332 'main_id' => $mainContact['id'],
3333 'other_id' => $otherContact['id'],
3334 ));
3335 $contacts = $this->callAPISuccess('contact', 'get', $this->_params);
3336 $this->assertEquals($otherContact['id'], $contacts['id']);
3337 }
3338
3339 /**
3340 * Test merging 2 contacts.
3341 */
3342 public function testMerge() {
3343 $this->createLoggedInUser();
3344 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params);
3345 $retainedContact = $this->callAPISuccess('contact', 'create', $this->_params);
3346 $this->callAPISuccess('contact', 'merge', array(
3347 'to_keep_id' => $retainedContact['id'],
3348 'to_remove_id' => $otherContact['id'],
3349 'auto_flip' => FALSE,
3350 ));
3351
3352 $contacts = $this->callAPISuccess('contact', 'get', $this->_params);
3353 $this->assertEquals($retainedContact['id'], $contacts['id']);
3354 $activity = $this->callAPISuccess('Activity', 'getsingle', array(
3355 'target_contact_id' => $retainedContact['id'],
3356 'activity_type_id' => 'Contact Merged',
3357 ));
3358 $this->assertEquals(date('Y-m-d'), date('Y-m-d', strtotime($activity['activity_date_time'])));
3359 $activity2 = $this->callAPISuccess('Activity', 'getsingle', array(
3360 'target_contact_id' => $otherContact['id'],
3361 'activity_type_id' => 'Contact Deleted by Merge',
3362 ));
3363 $this->assertEquals($activity['id'], $activity2['parent_id']);
3364 $this->assertEquals('Normal', civicrm_api3('option_value', 'getvalue', array(
3365 'value' => $activity['priority_id'],
3366 'return' => 'label',
3367 'option_group_id' => 'priority',
3368 )));
3369
3370 }
3371
3372 /**
3373 * Test merging 2 contacts with delete to trash off.
3374 *
3375 * We are checking that there is no error due to attempting to add an activity for the
3376 * deleted contact.
3377 *
3378 * CRM-18307
3379 */
3380 public function testMergeNoTrash() {
3381 $this->createLoggedInUser();
3382 $this->callAPISuccess('Setting', 'create', array('contact_undelete' => FALSE));
3383 $otherContact = $this->callAPISuccess('contact', 'create', $this->_params);
3384 $retainedContact = $this->callAPISuccess('contact', 'create', $this->_params);
3385 $this->callAPISuccess('contact', 'merge', array(
3386 'to_keep_id' => $retainedContact['id'],
3387 'to_remove_id' => $otherContact['id'],
3388 'auto_flip' => FALSE,
3389 ));
3390 $this->callAPISuccess('Setting', 'create', array('contact_undelete' => TRUE));
3391 }
3392
3393 /**
3394 * Ensure format with return=group shows comma-separated group IDs.
3395 *
3396 * CRM-19426
3397 */
3398 public function testContactGetReturnGroup() {
3399 // Set up a contact, asser that they were created.
3400 $contact_params = array(
3401 'contact_type' => 'Individual',
3402 'first_name' => 'Test',
3403 'last_name' => 'Groupmember',
3404 'email' => 'test@example.org',
3405 );
3406 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3407 $this->assertEquals(0, $create_contact['is_error']);
3408 $this->assertInternalType('int', $create_contact['id']);
3409
3410 $created_contact_id = $create_contact['id'];
3411
3412 // Set up multiple groups, add the contact to the groups.
3413 $test_groups = array('Test group A', 'Test group B');
3414 foreach ($test_groups as $title) {
3415 // Use this contact as group owner, since we know they exist.
3416 $group_params = array(
3417 'title' => $title,
3418 'created_id' => $created_contact_id,
3419 );
3420 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3421 $this->assertEquals(0, $create_group['is_error']);
3422 $this->assertInternalType('int', $create_group['id']);
3423
3424 $created_group_ids[] = $create_group['id'];
3425
3426 // Add contact to the new group.
3427 $group_contact_params = array(
3428 'contact_id' => $created_contact_id,
3429 'group_id' => $create_group['id'],
3430 );
3431 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3432 $this->assertEquals(0, $create_group_contact['is_error']);
3433 $this->assertInternalType('int', $create_group_contact['added']);
3434 }
3435
3436 // Use the Contact,get API to retrieve the contact
3437 $contact_get_params = array(
3438 'id' => $created_contact_id,
3439 'return' => 'group',
3440 );
3441 $contact_get = $this->callApiSuccess('Contact', 'get', $contact_get_params);
3442 $this->assertInternalType('array', $contact_get['values'][$created_contact_id]);
3443 $this->assertInternalType('string', $contact_get['values'][$created_contact_id]['groups']);
3444
3445 // Ensure they are shown as being in each created group.
3446 $contact_group_ids = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3447 foreach ($created_group_ids as $created_group_id) {
3448 $this->assertContains($created_group_id, $contact_group_ids);
3449 }
3450 }
3451
3452 /**
3453 * CRM-20144 Verify that passing title of group works as well as id
3454 * Tests the following formats
3455 * contact.get group='title1'
3456 * contact.get group=id1
3457 */
3458 public function testContactGetWithGroupTitle() {
3459 // Set up a contact, asser that they were created.
3460 $contact_params = array(
3461 'contact_type' => 'Individual',
3462 'first_name' => 'Test2',
3463 'last_name' => 'Groupmember',
3464 'email' => 'test@example.org',
3465 );
3466 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3467 $created_contact_id = $create_contact['id'];
3468 // Set up multiple groups, add the contact to the groups.
3469 $test_groups = array('Test group C', 'Test group D');
3470 foreach ($test_groups as $title) {
3471 $group_params = array(
3472 'title' => $title,
3473 'created_id' => $created_contact_id,
3474 );
3475 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3476 $created_group_id = $create_group['id'];
3477
3478 // Add contact to the new group.
3479 $group_contact_params = array(
3480 'contact_id' => $created_contact_id,
3481 'group_id' => $create_group['id'],
3482 );
3483 $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3484 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => $title, 'return' => 'group'));
3485 $this->assertEquals(1, $contact_get['count']);
3486 $this->assertEquals($created_contact_id, $contact_get['id']);
3487 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3488 $this->assertContains((string) $create_group['id'], $contact_groups);
3489 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => $created_group_id, 'return' => 'group'));
3490 $this->assertEquals($created_contact_id, $contact_get2['id']);
3491 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3492 $this->assertContains((string) $create_group['id'], $contact_groups2);
3493 $this->callAPISuccess('group', 'delete', array('id' => $created_group_id));
3494 }
3495 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3496 }
3497
3498 /**
3499 * CRM-20144 Verify that passing title of group works as well as id
3500 * Tests the following formats
3501 * contact.get group=array('title1', title1)
3502 * contact.get group=array('IN' => array('title1', 'title2)
3503 */
3504 public function testContactGetWithGroupTitleMultipleGroups() {
3505 $description = "Get all from group and display contacts.";
3506 $subFile = "GroupFilterUsingContactAPI";
3507 // Set up a contact, asser that they were created.
3508 $contact_params = array(
3509 'contact_type' => 'Individual',
3510 'first_name' => 'Test2',
3511 'last_name' => 'Groupmember',
3512 'email' => 'test@example.org',
3513 );
3514 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3515 $created_contact_id = $create_contact['id'];
3516 $createdGroupsTitles = $createdGroupsIds = array();
3517 // Set up multiple groups, add the contact to the groups.
3518 $test_groups = array('Test group C', 'Test group D');
3519 foreach ($test_groups as $title) {
3520 $group_params = array(
3521 'title' => $title,
3522 'created_id' => $created_contact_id,
3523 );
3524 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3525 $created_group_id = $create_group['id'];
3526 $createdGroupsIds[] = $create_group['id'];
3527 $createdGroupTitles[] = $title;
3528 // Add contact to the new group.
3529 $group_contact_params = array(
3530 'contact_id' => $created_contact_id,
3531 'group_id' => $create_group['id'],
3532 );
3533 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3534 }
3535 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => $createdGroupTitles, 'return' => 'group'));
3536 $this->assertEquals(1, $contact_get['count']);
3537 $this->assertEquals($created_contact_id, $contact_get['id']);
3538 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3539 foreach ($createdGroupsIds as $id) {
3540 $this->assertContains((string) $id, $contact_groups);
3541 }
3542 $contact_get2 = $this->callAPIAndDocument('contact', 'get', array('group' => array('IN' => $createdGroupTitles)), __FUNCTION__, __FILE__, $description, $subFile);
3543 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => array('IN' => $createdGroupTitles), 'return' => 'group'));
3544 $this->assertEquals($created_contact_id, $contact_get2['id']);
3545 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3546 foreach ($createdGroupsIds as $id) {
3547 $this->assertContains((string) $id, $contact_groups2);
3548 }
3549 foreach ($createdGroupsIds as $id) {
3550 $this->callAPISuccess('group', 'delete', array('id' => $id));
3551 }
3552 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3553 }
3554
3555 /**
3556 * CRM-20144 Verify that passing title of group works as well as id
3557 * Tests the following formats
3558 * contact.get group=array('title1' => 1)
3559 * contact.get group=array('titke1' => 1, 'title2' => 1)
3560 * contact.get group=array('id1' => 1)
3561 * contact.get group=array('id1' => 1, id2 => 1)
3562 */
3563 public function testContactGetWithGroupTitleMultipleGroupsLegacyFormat() {
3564 // Set up a contact, asser that they were created.
3565 $contact_params = array(
3566 'contact_type' => 'Individual',
3567 'first_name' => 'Test2',
3568 'last_name' => 'Groupmember',
3569 'email' => 'test@example.org',
3570 );
3571 $create_contact = $this->callApiSuccess('Contact', 'create', $contact_params);
3572 $created_contact_id = $create_contact['id'];
3573 $createdGroupsTitles = $createdGroupsIds = array();
3574 // Set up multiple groups, add the contact to the groups.
3575 $test_groups = array('Test group C', 'Test group D');
3576 foreach ($test_groups as $title) {
3577 $group_params = array(
3578 'title' => $title,
3579 'created_id' => $created_contact_id,
3580 );
3581 $create_group = $this->callApiSuccess('Group', 'create', $group_params);
3582 $created_group_id = $create_group['id'];
3583 $createdGroupsIds[] = $create_group['id'];
3584 $createdGroupTitles[] = $title;
3585 // Add contact to the new group.
3586 $group_contact_params = array(
3587 'contact_id' => $created_contact_id,
3588 'group_id' => $create_group['id'],
3589 );
3590 $create_group_contact = $this->callApiSuccess('GroupContact', 'create', $group_contact_params);
3591 }
3592 $contact_get = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupTitles[0] => 1), 'return' => 'group'));
3593 $this->assertEquals(1, $contact_get['count']);
3594 $this->assertEquals($created_contact_id, $contact_get['id']);
3595 $contact_groups = explode(',', $contact_get['values'][$created_contact_id]['groups']);
3596 foreach ($createdGroupsIds as $id) {
3597 $this->assertContains((string) $id, $contact_groups);
3598 }
3599 $contact_get2 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupTitles[0] => 1, $createdGroupTitles[1] => 1), 'return' => 'group'));
3600 $this->assertEquals(1, $contact_get2['count']);
3601 $this->assertEquals($created_contact_id, $contact_get2['id']);
3602 $contact_groups2 = explode(',', $contact_get2['values'][$created_contact_id]['groups']);
3603 foreach ($createdGroupsIds as $id) {
3604 $this->assertContains((string) $id, $contact_groups2);
3605 }
3606 $contact_get3 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupsIds[0] => 1), 'return' => 'group'));
3607 $this->assertEquals($created_contact_id, $contact_get3['id']);
3608 $contact_groups3 = explode(',', $contact_get3['values'][$created_contact_id]['groups']);
3609 foreach ($createdGroupsIds as $id) {
3610 $this->assertContains((string) $id, $contact_groups3);
3611 }
3612 $contact_get4 = $this->callAPISuccess('contact', 'get', array('group' => array($createdGroupsIds[0] => 1, $createdGroupsIds[1] => 1), 'return' => 'group'));
3613 $this->assertEquals($created_contact_id, $contact_get4['id']);
3614 $contact_groups4 = explode(',', $contact_get4['values'][$created_contact_id]['groups']);
3615 foreach ($createdGroupsIds as $id) {
3616 $this->assertContains((string) $id, $contact_groups4);
3617 }
3618 foreach ($createdGroupsIds as $id) {
3619 $this->callAPISuccess('group', 'delete', array('id' => $id));
3620 }
3621 $this->callAPISuccess('contact', 'delete', array('id' => $created_contact_id, 'skip_undelete' => TRUE));
3622 }
3623
3624 /**
3625 * Test the prox_distance functionality works.
3626 *
3627 * This is primarily testing functionality in the BAO_Query object that 'happens to be'
3628 * accessible via the api.
3629 */
3630 public function testContactGetProximity() {
3631 CRM_Core_Config::singleton()->geocodeMethod = 'CRM_Utils_MockGeocoder';
3632 $this->individualCreate();
3633 $contactID = $this->individualCreate();
3634 $this->callAPISuccess('Address', 'create', [
3635 'contact_id' => $contactID,
3636 'is_primary' => 1,
3637 'city' => 'Whangarei',
3638 'street_address' => 'Dent St',
3639 'geo_code_1' => '-35.8743325',
3640 'geo_code_2' => '174.4567136',
3641 'location_type_id' => 'Home',
3642 ]);
3643 $contact = $this->callAPISuccess('Contact', 'get', [
3644 'prox_distance' => 100,
3645 'prox_geo_code_1' => '-35.72192',
3646 'prox_geo_code_2' => '174.32034',
3647 ]);
3648 $this->assertEquals(1, $contact['count']);
3649 $this->assertEquals($contactID, $contact['id']);
3650 }
3651
3652 public function testLoggedInUserAPISupportToken() {
3653 $description = "Get contact id of the current logged in user";
3654 $subFile = "ContactIDOfLoggedInUserContactAPI";
3655 $cid = $this->createLoggedInUser();
3656 $contact = $this->callAPIAndDocument('contact', 'get', array('id' => 'user_contact_id'), __FUNCTION__, __FILE__, $description, $subFile);
3657 $this->assertEquals($cid, $contact['id']);
3658 }
3659
3660 /**
3661 * @param $groupID
3662 * @param $contact
3663 */
3664 protected function putGroupContactCacheInClearableState($groupID, $contact) {
3665 // We need to force the situation where there is invalid data in the cache and it
3666 // is due to be cleared.
3667 CRM_Core_DAO::executeQuery("
3668 INSERT INTO civicrm_group_contact_cache (group_id, contact_id)
3669 VALUES ({$groupID}, {$contact['id']})
3670 ");
3671 CRM_Core_DAO::executeQuery("UPDATE civicrm_group SET cache_date = '2017-01-01'");
3672 // Reset so it does not skip.
3673 Civi::$statics['CRM_Contact_BAO_GroupContactCache']['is_refresh_init'] = FALSE;
3674 }
3675
3676 /**
3677 * CRM-21041 Test if 'communication style' is set to site default if not passed.
3678 */
3679 public function testCreateCommunicationStyleUnset() {
3680 $this->callAPISuccess('Contact', 'create', array(
3681 'first_name' => 'John',
3682 'last_name' => 'Doe',
3683 'contact_type' => 'Individual')
3684 );
3685 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Doe'));
3686 $this->assertEquals(1, $result['communication_style_id']);
3687 }
3688
3689 /**
3690 * CRM-21041 Test if 'communication style' is set if value is passed.
3691 */
3692 public function testCreateCommunicationStylePassed() {
3693 $this->callAPISuccess('Contact', 'create', array(
3694 'first_name' => 'John',
3695 'last_name' => 'Doe',
3696 'contact_type' => 'Individual',
3697 'communication_style_id' => 'Familiar',
3698 ));
3699 $result = $this->callAPISuccessGetSingle('Contact', array('last_name' => 'Doe'));
3700 $params = array(
3701 'option_group_id' => 'communication_style',
3702 'label' => 'Familiar',
3703 'return' => 'value',
3704 );
3705 $optionResult = civicrm_api3('OptionValue', 'get', $params);
3706 $communicationStyle = reset($optionResult['values']);
3707 $this->assertEquals($communicationStyle['value'], $result['communication_style_id']);
3708 }
3709
3710 /**
3711 * Test that creating a contact with various contact greetings works.
3712 */
3713 public function testContactGreetingsCreate() {
3714 $contact = $this->callAPISuccess('Contact', 'create', array('first_name' => 'Alan', 'last_name' => 'MouseMouse', 'contact_type' => 'Individual'));
3715 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3716 $this->assertEquals('Dear Alan', $contact['postal_greeting_display']);
3717
3718 $contact = $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'postal_greeting_id' => 2));
3719 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3720 $this->assertEquals('Dear Alan MouseMouse', $contact['postal_greeting_display']);
3721
3722 $contact = $this->callAPISuccess('Contact', 'create', array('organization_name' => 'Alan\'s Show', 'contact_type' => 'Organization'));
3723 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting, addressee, email_greeting'));
3724 $this->assertEquals('', $contact['postal_greeting_display']);
3725 $this->assertEquals('', $contact['email_greeting_display']);
3726 $this->assertEquals('Alan\'s Show', $contact['addressee_display']);
3727 }
3728
3729 /**
3730 * Test that creating a contact with various contact greetings works.
3731 */
3732 public function testContactGreetingsCreateWithCustomField() {
3733 $ids = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__, __FILE__);
3734 $contact = $this->callAPISuccess('Contact', 'create', array('first_name' => 'Alan', 'contact_type' => 'Individual', 'custom_' . $ids['custom_field_id'] => 'Mice'));
3735
3736 // Change postal greeting to involve a custom field.
3737 $postalOption = $this->callAPISuccessGetSingle('OptionValue', array('option_group_id' => 'postal_greeting', 'filter' => 1, 'is_default' => 1));
3738 $this->callAPISuccess('OptionValue', 'create', array(
3739 'id' => $postalOption['id'],
3740 'name' => 'Dear {contact.first_name} {contact.custom_' . $ids['custom_field_id'] . '}',
3741 'label' => 'Dear {contact.first_name} {contact.custom_' . $ids['custom_field_id'] . '}',
3742 ));
3743
3744 // Update contact & see if postal greeting now reflects the new string.
3745 $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'last_name' => 'MouseyMousey'));
3746 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3747 $this->assertEquals('Dear Alan Mice', $contact['postal_greeting_display']);
3748
3749 // Set contact to have no postal greeting & check it is correct.
3750 $this->callAPISuccess('Contact', 'create', array('id' => $contact['id'], 'postal_greeting_id' => 'null'));
3751 $contact = $this->callAPISuccessGetSingle('Contact', array('id' => $contact['id'], 'return' => 'postal_greeting'));
3752 $this->assertEquals('', $contact['postal_greeting_display']);
3753
3754 //Cleanup
3755 $this->callAPISuccess('OptionValue', 'create', array('id' => $postalOption['id'], 'name' => 'Dear {contact.first_name}'));
3756 $this->customFieldDelete($ids['custom_field_id']);
3757 $this->customGroupDelete($ids['custom_group_id']);
3758 }
3759
3760 }