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