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