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