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